StencilJS fundamentals

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to this video on stencil fundamentals my name's Carl we're going to understand what stencil is for a start so stencils a library that helps us create web components of standard web components which is great because it means we can use those components in the Hana HTML based application and it allows us to use modern constructs like JSX and typescript to create the component so it allows us to create the components quicker and more robust Lee than it would do using the native Dom api's and the other big selling point of stencil is that it will polyfill browsers that don't support web components yet which are edge and ie so it allows us to create components using modern constructs really quickly target in any major browser so this all sounds pretty cool let us try it out we're in for yes code we're going to create a new stencil project using the init stencil NPM command we then get to choose the project type which is going to be component because we're going to create a couple of components we'll give the project a name and confirm that and then it very quickly creates our project the project contains an example component so we can start to get comfortable with what stencil components look like so we can immediately see that they're strongly typed with typescript we've also got HTML page in our project as well where we can test the consumption of the components as well to run the project we can use NPM star in the right directory and after a few seconds the HTML page opens with our rendered component let's hop back into our visual studio code project and we'll start to build our very own alert component we've started by copying the example component now renaming it might alert and we're removing the component tests and the readme file for now a component CSS is fine to be empty for the moment we're going to remove all the example code from the component so we just left with the bare minimum the tag name for the component is going to be my - and we specify that in the component decorator a method called render is where we define what is output to the Dom from the component and we use JSX to define that we're just going to output the text this is an important alert the final thing that we need to do is name our class my alert let's save the file and then let's go over to our index.html and let's consume our component save that if our UPS not running we can do an NPM start but if it is I can simply flip over to it and we'll see our components rendered so we've implemented a very basic component there we're now going to make the component a little bit more flexible when they use props to allow the consumer to configure the text so let's go back to visual studio code and go back to our component and import the prop decorator from stencil we can then use that decorator to create a text prop and more default it to this is an important alert and then we can reference that prop in our JSX and if we look at the rendered page we get this is an important alert because that's the default text for the component but if we change the consuming code in our HTML file to pass in some different text then we'll see that different text rendered on the HTML page we can interact with the text property through JavaScript as well so let's add a button and when that button is clicked let's change the alert text so we've opened up a script tag got a reference to the button we're going to create an event listener on the click event and in that event listener we're going to get a reference to the alert and then we're going to set the text property - this was a very important alert so let's save the file we'll go to the rendered page click the button and we can see that the text has changed so one very important thing to understand is when the props change the component is re-rendered let's move on to component styling now so let's go back to vs code we'll go back to our component and we can specify the CSS file that the stars are in using the style URL in the component decorator we're going to change our component to render a paragraph tag rather than a div tag we're just then going to go over to the CSS file and give that paragraph tag some style so if we now go back to the rendered page because we've introduced that new CSS file into our build will refresh the browser and we can see our style coming through so this is looking fantastic as well as being able to encapsulate behavior we can encapsulate styling as well into our components but let's double check that that style is encapsulated we're gonna add another paragraph tag under the button with some text in let's save the file look at the rendered page and we can see that the styles are leaked out so what's going on so let's inspect the style using dev tools and we can see our paragraph we could see a style being associated with it but we can see the style is coming from a global style tag that's obviously going to get picked up from all the paragraph tags on the page so at the moment the component isn't encapsulating the Styles so what we can do is switch the shadow Dom on in our component that should encapsulate the Styles we do that in the component decorator we simply set shadow equals true we want to have a look at this in IE as well as chrome so let's run in prod mode and we can do that with a - - prod after MPM start in the terminal it'll take a few seconds to start up looks like it's worked let's go and inspect in dev tools and we could see our paragraph tag is inside the shadow Dom so the stars aren't leaking out we're going to take a copy of the browser path and have a look at this in IE and remember ie has no shadow Dom and that seems to have worked which is good news so let's inspect the Dom there's no shadow Dom as we expected we could see a clasp has been injected on a paragraph tag and the style has been scoped with that class so stencils using scope styles as a workaround for not having the shadow Dom in IE but let's think about the shadow Dom what that means for consumers what if they do want to style internal elements within a component so in our alert what if they wanted to increase the font size at the moment they can't really do that what about automated testing and element selectors that we write in our test scripts let's try and select the paragraph tag within our alert we can see that's not returned when we try and select it that shadow Dom is hiding it from us so the shadow Dom does cause knock-on problems we could use CSS properties for the styling but that is a bit glitchy in stencil at the moment automated testing tools that I really struggle with a shadow Dom at the moment so let's go back to our components and replace shadow with scoped in the component decorator and that should make the styling behave how it was behaving in IE we're going to restart the project and make sure all those changes make it into the build take a couple of seconds we could see that appears to have worked let's inspect the style and we can see that we've got a scope style now and if we check in ie that's working as well great so let's just query and select that paragraph tag within our component and as I expected we can get to that fine so we don't need to do anything special within our automated testing so one of the biggest most important decisions that you're going to make when creating a web component is whether to use the shadow Dom or not and think about the automated testing do you need to do that think about styling do you need to let consumers style it if those answers are both yes then it's worth considering not having the shadow Dom in the component we're going to move on now I'm going to give our component a bit more flexibility we're going to have a kind property and that can be info success or error and that will dictate the background color of the alert and will default the property info and we're going to use that kind prop value is the class name on the paragraph tag and in our CSS file it means that we can have different rules for the different kinds of alerts so remove the colors from the main rule and then we'll add the different kinds and their colors we're going to go to our HTML file and let's consume this kind property so we'll have one alert that's info one that's success and then one that's an error and if we have a look at that works nicely so map in a prop to a CSS class is a neat way of varying the style for different prop values before we move on to our next topic we're gonna clean up our index.html we're going to get rid of the button and we're going to get rid of all the JavaScript so all that's left is our three different alerts on to our next topic which is going to be state and these are local variables within the component that when changed will cause the component to re-render and these are useful when the component needs to be interactive so in our alert component we're going to add an acknowledge button and when the user clicks that button the alert will hide so we're going to start by importing the state decorator from stencil we can use that on an acknowledged boolean variable the defaults to false but when it's true that should hide the alert we're now going to rearrange our JSX slightly before add in our acknowledge button now when the button is clicked we want to change that acknowledged state value so let's create an onclick handler we use an arrow function for the handler so that we get access to the class instance using this so we can simply set our acknowledge state to true the styling on the paragraph tag is going to get more complex because it's going to depend on the acknowledge state as well as the kind prop we're going to extract that logic out to a function we're still going to have the kind class but if the alert is acknowledged we're going to add an acknowledge class so now we can ref that function on our paragraph tag before we move on to define the CSS let's make a few corrections in the function we need brackets around the eggnog but in the function and I acknowledge needs a D on the end and in our CSS then when the paragraph tag has got the act knowledge classed is not displayed and the acknowledge but on his borderless and it's got small faint text so let's give this a try we're gonna get rid of some old browser tabs will refresh and then we can see our acknowledge buttons and if we click those the alerts disappear to prove to ourselves that the components re-rendering when state changes will console.log the word render in the render method I'm gonna make sure we're running the dev build rather than the prod build so that we can see those console log messages so NPM start to do that wait a few seconds we'll open up dev tools on the console and we can see we've had three renders from our three alerts and when we click the acknowledge button we get another render and that proves that changing state rearend as a component I'm just gonna remove that console log now before we go on to our next topic and our next topic is going to be event so exposing event from our component and the example that we're going to do in our alert component is an acknowledge event that will tell consumers when an alert has been acknowledged so we'll start by importing the event decorator and the event emitter type from stencil we can then use those to declare our acknowledge event we then raised the event by calling emit on that event variable so the event has been raised when the acknowledge button is clicked let's listen to that event then in our HTML page we're going to listen on the document so that we can catch the event for all three alerts and we're just going to log out the alert text to the console in the event listener and if we give this a try and acknowledge the alerts we'll see that the text is output to the console let's enhance our event to have an argument and the argument will contain when the alert was acknowledged we start by creating an interface for the argument type it's important to export the interface and in our case we're just going to have a whene property that is of type date on our acknowledge event property we're going to pass in our argument type to the event emitter type and then when we omit our event we can include the value of the when property so in our HTML page let's include our event argument which is in the detail property and this is the case for any component event that we create our custom arguments for that event are in the detail prop so if we give this a try acknowledge the alerts we'll see that the date and time is logged out to the console a next topic that we're going to look at is listening to events we've seen how we can listen to events on internal elements but how can we listen to events on the host element so we're going to change our implementation so that the user can click anywhere in the alert to acknowledge it so as part of that we're going to need to listen for a click event on the host element we can do that using the listen decorator so let's import that and then in the decorator we say what event we want to listen to which is click and the decorator decorates a method that's going to handle the event and we need to change that from an arrow function to a normal method or give the Methodist slightly different name as well we no longer need an act knowledge button so we're going to change that to a span and we'll tweak the CSS to target a span instead of a button and because it's a span we don't need to remove the border and if we give this a try will click the acknowledge text and it disappears we'll click anywhere else in the alert and it also disappears good our next topic is lifecycle methods and these are methods that we can implement in our component to execute logic at various points in the components life and this page in the stance of Jaques shows us these methods and when they get him vocht in the lifecycle we've already used the render method the other method that's heavily used is component dead load and that's after the first render when the components been loaded into the dom and component did update occurs when some state has changed or a prop has changed and the componentry renders and updates so we're going to have a little play around with both the component did a load and did update methods in our alert component so we're simply going to add these methods to our alert component an output fully loaded to the console when the components loaded and then component updated when the components been updated we'll give this a try and we'll see straight away we've got our components fully loaded and then when we acknowledge the alerts we get the component updated logged we're just going to remove those lifecycle methods now because we don't actually need them in our alert component we're going to move on now to create a more sophisticated component in fact it's going to be a compound component so that's two components working together to create a sophisticated user experience we're going to create a tabs component and one component is going to be the container for all the tabs and then we've got a component for the tabs themselves and we're going to start by focusing on the individual tab component so we'll copy our alert component there's a starting point and we'll clear the stuff out and this components going to be called my tab we'll start by thinking how we want our component to be consumed so in our HTML page let's just write out an instance of the components we want a name prompt to uniquely name the tab and we also want to specify what is rendered within the tab we'll create a second tab give it a different name and this time we'll render its caption in bold we also want to be able to specify that a tab is active so let's add an active prop to the second tab we'll start the implementation then let's import the prop decorator so we can add the name and the active prop nothing new there we know how to do those we're going to render a div that's got a CSS class on it and the class depends on whether the tab is active so we're going to use a function to calculate that so the div is always going to have a my tab class but if it's active it'll have an active class as well so we can add the CSS then so we're going to give each tab some padding and a pointer cursor and then active tabs will have a blue underline and if we have a look at the output in the browser we see that coming through but if we look a little closer by inspecting the Dom we will see that our tab caption is outside the div and not inside the div so in our component we need some way of saying this is where we want the child content to be rendered luckily if there's a way to do that and we can use what's called a slot to do that nice and simple let's give it a try refresh the browser and we will see now that our tab captions are within our div so our next job is to add a tab activate event when the tab has been clicked it will start by importing the bits and pieces from stencil create an interface for the arguments which is just going to bring back the tab name we'll then declare our event variable passing in our argument type and we want to listen to when the tabs clicked so let's create a handler for that and then when it's clicked we want to omit that tab activate event including the tab name and let's not forget to make the tab active as well let's consume that event then in our HTML page I'm just going to comment the alert out so we can see our tab more clearly and again we're going to listen for the tab activate event on the document and we're going to output the tab name when that's been raised we get access to the tab name through the detail prop in the event argument so give it a try have a look at the console click the tabs and we can see the tab name has been output we can also see the tab being activated as well with the active style so we making good progress but we only want one tab to be active at any one time so we could do with a component that wraps around our tabs and manages which tab is active it'll be nice to specify what tab is active by default as well using an active tab property so let's implement this we'll close the files down and then we're going to take a copy of our mytab CSS and my tab tsx and we're just going to rename those my tabs so we're clear out the CSS and we're going to clear everything out of our component but it's going to be named my tabs we're going to start the implementation by managing which tab is active so let's import the listened decorator and the argument for the tab activate event and we'll create a listener for that event we can strongly type the event listener arguments by using the event generic-type and passing in our event type looks like we've not exported our tab activate event so let's go and correct that now everything's compiled in fine we're going to leave that handler there and we're gonna go to the render method and we're just going to render a div with a slot inside so that's just gonna render the tabs within it and we'll give our div a class name as well so let's think about a tab activate Handler again somehow we need to get all the tabs and make sure the one that's just been activated it's the only one that's active so it'd be handy to get a Dom reference to a host element because then we can do a Dom query within that to find all the tabs so the way that we get a reference to our host element is using the element decorator so let's import that and then we can declare a variable with that element decorator that's going to give it a reference to the host element let's have a lowercase e for element and we can use an element variable to get access to our container div and then we can get the children within that div we're then going to turn this result into an array so that we can use the filter method to just filter out anything except for the my tab instances and let's make that check case insensitive so we've got a head ins so let's loop around all those headings and we'll deactivate all the tabs that haven't just been activated get better try them refresh the browser and click on the tabs and we can see that the activation is being managed nicely now let's add a little bit of styling so let's go over to our CSS file and we're going to turn our div into a flexbox so if we go back to the browser and refresh it and we'll see that we've got horizontal tabs now let's go to our HTML file and we're going to remove that active property so none of the tabs are active by default let's go to the browser so we have to click on a tab to make one of the tabs active to improve the consumption we're going to make the first tab active by default if none has been specified we can use the component did a load life cycle method to do that work we're going to need to get our tab elements again so we're just going to extract the expression that we had before into a function so now when the components loaded we can get the head ins check if one of active and if not we can set the first one to be active but we only want to do this if there's more than one tab so let's give this a try refresh the browser and our first tab is active and the activation still works nicely moving back to our HTML page we will see that we've got that active tab property on the my tabs component that's not implemented yet so let us implement that now we'll start by importing the prop decorator we're also going to import a watch decorator which we'll use a little bit later on or create a prop first and we're going to make our prop mutable because we're going to change its value in the tab activate event we're just going to comment out the previous implementation so when I active tab changes we want to set the active prop on the tabs so it can create a watch on active tab and then a method that is going to handle changes so we'll start by getting all our tabs again and certainly active prop on each tab accordingly we can remove the commented out content in the handle tab activated method we're going to refactor I component did load event to be driven from the active tab property now so if it's undefined we do what we did before if it's got a value then we call I change handler passing in the active tab and that first branch rather than set in the active prop on the first tab we're just going to set the tabs active tab name and it'll be the change handler that sets the active property on each tab so we're ready to give it a go let's just go to our HTML file so the second tab should be active by default which it is and we can still click the tabs and they work perfectly so let's have a quick recap then in components we've got props that allow us to configure the component we can watch props and handle changes to those we can change your prop internally and whenever a prop changes whether it's externally or internally the component will rerender we can get access to the host element using the element decorator and then we can use the Dom API to manipulate the component at runtime perhaps in a lifecycle methods such as component did load component is styled using CSS props and state can drive the CSS class names that elements have we can expose events using the event decorator we can listen to events on the host element using the listen decorator and the state or internal variables that when changed force the component to re-render and all these features give us phenomenal power to build standard web components that can target any major browser and that concludes the video I hope you enjoyed it
Info
Channel: Carl Rippon
Views: 7,262
Rating: 4.949367 out of 5
Keywords: stenciljs, javascript, webcomponents
Id: SCB3X2ApYWc
Channel Id: undefined
Length: 28min 36sec (1716 seconds)
Published: Wed Jul 17 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.