Fundamentals of Web Components

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello my name is bashar abu karma and welcome to this course about fundamentals of web components web components is a suite of different technologies allowing us to create reusable custom elements and we can encapsulate away our web components functionality from the rest of our code and we can reuse them in any of our web applications the components consist of three main technologies the custom elements is a set of javascript apis that is allowing us to define custom elements and their behavior which can then be used in our user interface shadow dom is again set of javascript apis for attaching an encapsulated shadow dom3 to an element and this is rendered separately from the main document dom in this way we can keep an elements feature private so they can be scripted and styled without the fear of collision with other parts of the document and the last one is the html templates and these are basically the template and slot elements which are enabling us to write markup templates that are not displayed in the rendered page these can be then reused multiple times as the basis of our custom elements structure with web components without needing an external framework we can create our own custom components we can share them between our web applications web components functionality is coming with the browsers most popular browsers are supporting the most of the standards about web components for unsupported cases we will be seeing how we can use polyfills to make this unsupported functionality to work with that browser so if you are ready let's start learning the building blocks which are the fundamentals of the web components in this course i will be using visual studio code as editor i will be using couple of plugins of it so i would suggest you to use this editor while following this course you can download the latest version here and install it by following the steps in the installation wizard the plugins i'm going to use are these command tagged templates and this live server this live server is going to be used to serve our index html through this visual studio code extension and these command text templates are going to be useful for syntax highlighting of our html markup written in text format the vs code is improving the productivity of our development so i would suggest you to use that one too during the course so let's start building web components first we will start with index html so here in the vs code i am creating a new file here and it is index html and we can use the code snippets from vs code by typing exclamation mark and here it is suggesting us this option this basic html markup so here we have the index.html and let's say the title is web components and saving this one and right clicking here and opening it with live server so this is an extension for for visual studio code and here it is the live server so clicking this one i opened the chrome side by side and the live server is running at this port localhost 5500 and the this is the page index.html we don't need to add the index.html part here if you just go with this way we are still receiving our page this is the title we set and this extension is like if we add anything right here let's say hello it is automatically restarting our application right here so this is a useful while we do our implementations we have html elements and we can see the list of them here and we are using them to build our application so there are h1 there are main and we have this div the buttons and the anchor tags and also there are lots of others we are not using so frequently and just like these elements we can create our own elements so we will do that so the web components is allowing us to create our own custom components we can create components with composing multiple built-in elements or custom elements within this way we create reusable components so for instance we can have our own custom button which can be showing progress indicator until our action is completed let's start with that but let's do it with the existing button first then we will build same thing with custom elements and we will see the real benefit of it now here in this page let's have a button [Music] and this is going to be printing lock after two seconds so let's say the button text will be print delayed log so here we have the button on this page i'm just zooming a bit here now when we click this button we will call a function so first let's assign uh assign the function right here the button has the attribute of on click and let's say our function name is long action so as soon as we click this button this function will be called and let's implement that function right here having a script block and in this script we will have the function this long action and we will just print let's say console.log hello console [Music] so saving this one the page is refreshed so when we click this one it's going to be printing this console look so let's open the developer tools here hitting f12 it is opening this part and in the console tab here we see the hello console is printed if i click multiple times here we see the log is printed by the way i implemented the function like this but let's use modern javascript features now let's replace this function with an arrow function so we are going to assign this function this arrow function is a variable first so we will have the variable and for variable we used to have the var keyboard but and now with the es6 we have the const or led keywords const is for the variables which are constant and let is for the variables which we can assign different values to it so let's say the variable is const let's say it is a long action and it here is the arrow function the empty parenthesis is just like this one we are not taking any parameters in this function and the arrow part and opening the curly braces and just moving this console look into this function and removing the old one so saving this one and if i click it here it is working so when we click the button we are triggering this function but currently it is not printing this output in delayed it is printing immediately so let's add delay to it again we are going to use another javascript functionality we will use set timeout and this is taking two parameters the first one is the callback function so this function will be called by when and we set the one in the second parameter let's say two thousand milliseconds so in two seconds this function will be called and in this function we will be just running this console log so saving it and let's click the button we don't see anything yet and the console log is printed now let's update this logging a bit more well it's not very clear when this trick when this action is called and when this console log is printed so let's do it this way here let's log the time let's print the date and let's also load the time when we run this console.log part so saving it so here i clicked it we have this output and then we have this hello console and it is exactly two seconds after the first one in an actual application this stila behavior can be seen in cases like sending data to backend or loading data from backend so in these circumstances we would want to show some kind of progress to user so user would be aware that the client is working on that action otherwise user cannot understand if the button is really clicked or if there is any action in progress or not so let's show some kind of progress here again let's go with a simple feedback let's just change the text of button to loading for that we will change the button text dynamically in this javascript so first let's get the reference to this button and let's assign it to variable here let's call it button and we will get this button with the document and the document is the object of the root node of this html document and it has functionalities like query by selector and we can pass the selector as the element name button so this would be looking for the button element in this html and then returning that element back to us or we can set id to this element let's say this is a classic button and we can get that button by querying it with its id we can pass the parameter like this with hash sign classic button so if we are querying based on the id we have to add the hash and then the id to it and we can also query based on the element without adding any prefix to it or we can query based on the the css class classes assigned to this element and in that case we use the dot so the the button may have a class of something like this btn so we can query it based on this one but let's go like this so we have the button with this id we got the reference to it and here when we are in progress we are going to change this button text to let's set like this button text content let's say it's going to be loading [Music] a simple text like this one but after this operation is completed we want to return back to the original value which is print delayed log so we can go like this we can either just copy and paste it here and we can just set the print delayed log so this would work but let's not repeat ourselves here let's have the the original value first like this let's say original button text which is just the button text content so we have the value then after the timeout we can just set it back so let's save this and let's click the button here the text is changed and returning back to the original value after the facing operation is completed so this is working but let's click this button a couple of more times so clicking multiple times and here we see there are problems with it one of the problem is we are able to click the button even there is an ongoing progress and here in the end we see the console logs are printed a couple of times and also the button is having this loading text even all delayed actions are done let's make sure user cannot click when the action is in progress so we will disable the button during that time let's do it right here now we are setting the text content of the button button has disabled attribute and we will set it like this button set attribute and the attribute name is disabled and this is actually a boolean but for value we can set anything we want in html elements we have to set the values as string so if any value is set for a boolean attribute it is considered as true so let's say it is true and after the time out we are going to back to enabled state which means we are going to remove the disabled property we cannot do it like this if we just set the button set attribute to false this is not going to work because element attributes are string so even we are setting the value of a boolean like true or false it is not actually processed as a boolean it is just processed as a string regardless of their value is considered as true in javascript so to enable the button we have to call remove attribute method of the button and we don't need to pass any true or false value to it we just say we want to remove the disabled attribute so let's save this and try this one so we will click multiple times but clicking the first one and clicking a couple of more times and we only see it is just running one one time and also we can see the button is disabled the the visibility of the text or overall coloring is changed now let's change the style of this button so here adding a style element right here in this head [Music] and let's have a class of ptn and we are going to use this class in this button let's say class is going to be btn and let's go step by step let's say the background color of this button will be a color like this one [Music] so this is blue color this one let's save it so the button is like this and let's set the text color the color as white and let's remove the border by setting border to none and let's also add some radius to the corners with the border radius let's say it is 7 pixel and also let's add some padding [Music] we are going to add padding to left and right and not the top and bottom so the for the top and bottom it's going to be zero but for the left and right it's going to be 2 r em and also let's set font family so we can do whatever we want here i'm just going like this one and let's add a box shadow here the x coordinate will be 0 pixel and the y coordinate will be 4 pixel and this is 40 pixel and the shadow color is going to be this one [Music] and it's going to be a bit transparent like this save it here we have a shadow right here of course you can set your own style this is just my example you don't have to do the exact things and here we have the button but this is not doing anything if we hover on it so it's not it looks like just an image so let's make it a bit more reactive so let's set ptn hover this is the style applied during our mouse is hover ring on the element so let's say the background color is going to be something like this so just typing this one 1d 8 0 f0 saving this one and if i hover the button it is a bit showing some changes and let's also set a color for the disabled btn disabled [Music] and let's say the background color will be like this 6 a a aa8f0 so this is going to be applied this disabled is going to be applied when the buttons disabled attribute is set let's try like this disabled is true saving it here we can see that this disabled style is applied and also since our this click function is setting the button attribute we will see the the effect right here here color is changed now the button looks better let's do one more enhancement on this button let's make this this loading text to be fading out to emphasize more about something is going on in the background so adding a new class right here let's call it fading and we are going to do an animation here so our parameter is animation and we are going to run the animation of fading we will define it below and this is going to be taking half seconds and it's going to be repeating infinitely and here we will define the keyframes key frames for this fading animation and in the zero percent it is going to be the color this this time let's change the color of our text so the color will be the color is like this 6 a a 8 f 0. so we will be using this disabled color and in the 50 the color will be white and [Music] in the 100 percent it is going to be this color once again so we can see the effect of it right here let's say fading and here we see the text is fading out and in now we are going to apply this style dynamically so when we click the button if and as soon as we are updating it like this showing the loading text disabling it and we will change we will add that class that fading to this element so we will call button and it has class list and in this list we are going to add the fading and after this operation is done we will remove that class from this class list we call remove and we will remove fading so saving this one and let's see how it's going to work here we are seeing the text is fading and as soon as the operation is completed we are back to our original button so we have completed our implementation now we have a button with some good enough feedback to user about an ongoing action so we extended capability of regular button with more user friendly button so far we haven't done anything about elements we created some basic scenario for ourselves to see the benefit of the web components next we will see how we can do these things with a custom element and we will see how it is turning this implementation to more reusable way now we have this button and we can use it in forms like login register but when we do that we will have to repeat ourselves let's pretend like we have such case let's change button text to login first and here in this script part let's update these variables let's say this is going to be just selecting all the buttons here and this is going to be a login button and let's also update this id let's call this one button login and here we are using the same id and let's update the method as just login and let's repeat the same steps for the register let's say we will have a register button right here just copying and pasting this one [Music] and this is for register we will have a register method and this button will have the register text in it and we will have the exact same things right here so let's say in the login we will just print let's say this is a login response we no longer need to print the date here we will not do that also here and in this one we will have let's select all the login buttons and replace it with the register button and we have this classic button register and using it right here and this function is register and let's say this is register let's remove this console.log and let's change this part to let's say this is going to be register response and we don't need to print the date anymore so saving this and we have two buttons the one is this one is login clicking this one here we are seeing the login response and if you click the register the register button is reflecting the the progress and we receive the register response here so these functions are almost identical the only difference is the real action this part so this is making it harder to reuse this logic but also in future if we want to update the behavior we have to find all the used places in our code base and update each one by one of course we can refactor this implementation by extracting these parts to separate functions and then we can use those functions both in this login and this register functions but instead of doing that we will convert this button to custom element the function here is dealing both with the behavior of our button and the actual action which is for instance a register or the login operation with custom elements we will be handling that element related operations like changing the text setting disabled setting different classes in it we will be handling within the custom element itself so instead of copying and pasting the implementation we can create our own custom button component and that component will be reusable because of the nature of web component so let's do that so here in this script part right after our functions let's create a class again we are using the class of es6 so we will have a class and let's name our class as button or we can say my button any name you want and this button is going to be extending html element in this element we have this constructor and if you are implementing the constructor then we have to call the super which is the html elements constructor and we have the basic element definition right here and so we will register this element by running custom elements define [Music] and we will give a name to our component and as a rule we have to have a name separated with dash so for my case i'm going to set my element my custom button is app dash button so we must have this dash in the name of our custom element that's the rule and as a second parameter we are passing the class having this button implementation and that is this button right here so this way we are defining a button element we will use it in our page and that element is actually this button class we have here so we can use this app button right now so if i go right here just adding this app button that's it let's save this for now we see nothing on the page but if we go to here in the elements tab here we have the login button we have the register and we have this app button right here but since there is nothing in it we don't have anything to display with it it is invisible so to make it visible we can set value to its inner html like this in here in the constructor after super i'm setting this this class this button which is actually an html element has this inner html and let's set it to we can set anything we want here let's say this is hello saving it and here we are seeing the hello and the same element is right here having the hello in it now we are going to move the implementation we have here like the text content change attribute disabled attribute change and the class list we will move that into this button but let's have an interaction to it first so just like any element custom element also has on click attribute and let's say we want to run this temp function we have here let's define it here so the temp is here [Music] and let's say this is temp so if we go and click this one here we see the temp is printed right here and if you click the register the register function is called now let's change the inner html part we can use the html elements here too so like this one we can say the button [Music] and we can say this is a button having a text like this let's say custom [Music] saving it and here we have this button and if i click it is printing the stamp this function is called and also we can set the class for it we can make this button look like this one so we can set the class again we are going to use the double quotes here so that we can type btn right here but since the inner html is also having this string assignment and since we are using this uh double quotes within our string we can just change this one to like this single quote [Music] we wrap it with single quote so that we can use the double quote within our actual string so let's save this one and here it is like the others so we have just seen the basics of an element now let's get rid of this temp function and this app button now we are going to replace this button with the f button we just added so just replacing the button with app dash button and the closing part also will be app dash button now let's save this now there are a couple of issue here let's focus to this custom button here just selecting this one here we have the app button having this class button and we in this app button we have this button element we are having this inner html within this app button so that's why we have this custom button right here so the the first thing is we no longer need to set the class for the app button we are we are not going to set a class for that one so removing it now it looks better because currently we are just styling this button not the app button the app button is wrapping the button component in it and the other problem is the even we set the login as the button text we are seeing this custom because this is this is coming from this one so we are actually rendering this button and we have the value here custom so in regular button we were setting the the text like a child element to it so you are setting the register inside of it we can do the same thing for this one too this new custom button but we will see that practice later for now let's pass this button text as attribute like this on click or this id so we will set text as login this can be any attribute name you want so i'm just using text so we can just remove the login part we are already setting this text right here and here in this button we can get that value like this this get attribute and our attribute name is text so this is going to be returning back the text let's assign it to a text variable here now we are going to use this text here and we can do it like this we can convert this string to string literals by having this in backticks not single quotes so in backticks we have this string this is string literals and for this part we can use this text variable like this dollar sign curly braces and in this curly braces we use the text this variable so saving it and here we are seeing the login text here and if we click the login button here we are seeing the style is broken here in this login function we are setting the style and attributes for the component this app button but in our previous implementation these changes for the actual button element so here we are seeing this button let's focus to this part when we click to it here it is setting the class and it's also setting the disabled but in reality these changes for the actual button element so our custom button element should be doing those updates in the button component it has in its inrange demo but let's simplify our functions here instead of setting these values like setting the content setting this disabled setting class let's set a single attribute on this custom button and based on that value we will do whatever needs to be done inside our components so let's say instead of doing these changes we will just set login button set attribute and let's call our attribute name is in progress and we will set it to true and after the progress is completed we are just going to remove this attribute so we will do like this we are going to login button remove attribute in progress so that's it and based on this attribute our custom component will do the rest so if we click the button like this so here we are seeing the in progress is edit and as soon as the operation is completed that attribute is gone now we need to react to the changes of this attribute so we cannot do that in this constructor in html element class there's a static method and let's implement it this method will be called when this button is defined as custom element and this is a static method and if you have java background this static is same with the one you use in java this is not specific to the object instance but it is used for whole class and in this method we will return so we will set get so it's going to be a get method and we will return array of attributes so method name is observed attributes [Music] and it's going to be return and array [Music] and this array will be containing the attributes we want to observe so for our case we are going to observe this in progress attribute again as string we are passing this in progress in this array and this will be triggering another method of this class to be called and that method is attribute [Music] changed call back this method takes three parameters the first one is the attribute name the second one is alt value for this attribute and the third one is the new value for this attribute so let's log them right here this is attribute alt value and new value [Music] so saving this one and let's open the console here clicking the login here it is saying in progress is initial value was null and initial old value was null and the new value is true so it is writing here and as soon as we remove the attribute this method is called once again and it is saying the in progress old value was true and now now so this is called because of we are specifically telling that we are observing the changes in the in progress attribute of this component so if you don't add this part let's remove it [Music] this method will not be called here we don't see that console.log so we must be adding the attribute we want to observe as this method name implies and whenever anything changes for that attribute this method will be called with the attribute name and the the value changes the old value and the new value now we know how to react to the changes of our attributes so let's do this implementation we have here this text changes this disabled setting the the class usages right here in this attribute change callback so removing this console log this method is going to be called for the in progress attribute but we would be observing multiple attributes so here we should be doing control about for which attribute this method is called for our case we only have one field here this one so i'm not going to do the checks here but keep in mind that this is going to be called with any element in this array so if we have multiple items then we should be doing our controls within this function so first let's get the button elements so we have this button right here and we can get that button within this element by running this elements query by selector so this is only going to be querying this element this selector we are going to pass within this element itself so this query selector and let's get just the button so we have the button reference right here and we we have seen this method is called when the in progress is set true and when the in progress is set to null when when it is removed so we will check this new value so if new value has any value in it if it is not null which means if it has any value in it any like any string value or anything then this is true so we will set button text content as loading and we will set button set attribute disabled as true [Music] and we will set button class list add fading [Music] and the else condition we will set the text content button text content as now we don't need to get the reference of the original value anywhere here because we are receiving this text this button text as attribute already so we can just use this one so we can assign the attribute text to the text content of this button element and we will remove the remove attribute of disabled and we will remove fading from this classlist so let's save this one now clicking the login and here we see this is working properly so with this way our actual function the action related function is slimmer we no longer need these parts and all we do here is we are just doing the action but we are also telling the the button itself that the action is in progress and the rest of the things like the disabling button setting styles are handled within the element now let's replace the register button with our component 2. so here it was this one let's change it to app button and let's remove this class let's set the text as register and we no longer need to pass the child text and let's update this function we will just call this register button and we will set attribute of in progress [Music] to true and we will remove this attribute here after our action is done remove attribute in progress by the way we no longer need to have this original button text because we are handling them handling that inside our element so the login function is like this we are starting the progress and we are telling the progress is done and same thing for the register button so both of these functions would be doing their own work but for simplicity we are just printing a lock like this so saving this one and trying the register button and here we are seeing the same styles and the things are applied for the register so if we check the implementation right here when we click the button we are setting in progress but the actual element this button is doing the changes here in the button element so it is setting the class setting the disabled setting the text for it so the those things are handled inside our custom element custom elements have life cycle methods these are called as custom element reactions and so far we have seen two of them the constructor and this attribute changed callback now let's see the others and let's see this on another component let's create a new one right here let's call this one as counter again extending html element [Music] and let's have the constructor so we will call super and let's console log each of these methods so in this one let's run constructor and let's make this component visible on the screen so let's set this inner html as let's say temporary and the other method is connected callback we will see when this method is called so this is going to console.log connected and the other one is this connected callback [Music] and this is going to be printing this connected [Music] and the next one is attribute change callback we have seen that one so it has attribute alt value new value let's say console.log attribute changed and the last one is adapted callback and let's say this is going to be printing adapted and let's define this element here custom elements defined and the element name is f-counter and the class is right here counter and let's use the counter here f counter and here we are seeing this is visible and in the console we see the logs the constructor and the connected so when our element is added to the screen this constructor is called and also this connected callback methods are called now let's do a scenario like this first let's let's remove these buttons removing this app button and removing the corresponding scripts so we only have the button this class and this counter again we will add buttons but this these are going to be doing something else so first let's add a button button and this is going to be for add we will when we click this add it's going to be adding this app counter to the screen and we will have another button app button and this is for remove and let's also remove this app counter and saving it and let's show these buttons separate lines so here in this style adding a new one right here we can use our element name like this f button [Music] and we can set display as block so they will be separated to their own lines now let's also make sure our app counter would be having same style so it's going to be shown on its own line currently it's not in our document but we will add it with this add button click operation so let's set our function for clicking we are going to call this add function and for remove we will call this remove function and let's define those functions right here so this is for add and this is remove [Music] so when we click the add button we will create an element of this app counter so we are going to programmatically create this app counter so with this way we will be seeing how these life cycle methods are working so here in this add function we are going to call document we are going to create an element and the element is this app counter so let's save this so at this step if we click the button we can see the console log of constructor so we are creating an instance of our component but it's not in our document tree yet and we also see this exception this is happening because we are setting this inner html in constructor but that element is not added to dom yet when we add this component directly to our html document just like any other element we do our code is working but when we go with programmatically it is failing so that's why we shouldn't be doing anything related to dom at the constructor so let's remove this inner html part saving it and clicking the add button again and here we see the constructor log is printed and we don't see any exception now we are going to add this element to our screen by document body append we are going to add this to our document but first let's assign it to a variable let's call it counter [Music] and here we will add this counter to document now saving this one and clicking the add and here we are seeing the constructor and connected and if we check the elements tab here we have right here the app counter it is added to the body this is the body and it is appended right here since we have no inner html set for this component there is nothing visible so this method is called this connected callback is called when our element is added to the dom so this is the method we should be doing all ui related things so we can set inner html right here this inner html is temporary saving this one clicking add and here we see the temporary is added and if we click multiple times we will see it is added right here so we have seen the importance of using this inner html in the connected callback but in our button we didn't do that so we need to fix it right here let's have connected callback [Music] and we will have these lines this text assignment part inside this connected callback so if we save it we will not see any changes but the implementation is more robust now if any time we dynamically generate this button component will properly work it's not going to be driving any exception or anything now we are adding this the counter to our page and let's implement the remove functionality so here we are going to run document query selector we are going to find the exact element and we can query it by like app counter there can be multiple app counters on the page but it's going to be returning the first one and we will just run remove function of it [Music] so this is going to be removed from the screen so saving this one and opening the console once again clicking the add and here we see the constructor and connected logs and if we click the remove the element is gone and also we see the disconnected message here which is printed because of this method so this disconnected callback function is called whenever our element is removed from the dom now let's add some functionality to this component let's say this component will be counting until to the number we set for it so let's say here when we are adding this counter to the screen we are setting an attribute for it let's say counter will have an attribute of let's say until and let's say we set it to five so so this counter is going to be counting until 5. now in the element implementation we used to use constructor for inner html but now we have a real use case now this component will have a state value so it's going to be having a count value we are going to count from 0 to the number we set in the attribute and best place to initialize this state is this constructor so let's say we will have a property of this class and it's going to be count so we will do it like this this will have a count and initially it's going to be zero and then here in the connected callback our component is now part of the dom so first let's show the count so this inner html will be this count and then let's get the until attribute so let's have until and we get it by this we'll have this attribute so we get it like this [Music] and we will update our count periodically so we will use another javascript functionality which is set interval just like settimeout it takes two parameters the first one is the callback function which will be called back in the each interval and the interval is set like this as a second parameter let's say this is going to be a run in every second so here this method is going to be called in every second so what we will do here is if this count is less than this until then let's increment incremented so this count will be [Music] increased by one and let's update our inner html with this new count this inner html is going to be this count so let's save this and let's add a counter here and here we can see it is counting from 0 to 5 and it is stopping there but in this implementation there is a critical flow now let's add a log right here in this set interval callback function let's console log [Music] interval is running and let's print a dynamic value like date now here now let's add the counter and here we are seeing interval is running interval is running and the count is done but this interval is still running so even our component has nothing to do on ui part our component is using resources so after we reach to the count we must be stopping this interval so the thing we need to do here is first this set interval is returning back a number back to us this is the id of our actual callback function so let's assign it to a property of this class like this this interval is the the returned value and here if we reach to the limit the to the until count then let's here in else condition we are going to clear the interval by running clear interval function with the interval id we have interval so saving this one adding the counter it is counting and now it is stopped so we are making sure our component is not using resources now let's do one more thing here refreshing the page adding a counter and clicking remove now we can see this even the element is gone we are still seeing this interval is running so if our component is not visible then it shouldn't be using the resources so we can use this disconnected callback to clear the resources so we will run once again clear interval right here in the disconnected callback so saving it adding the counter and removing it and we are not seeing this interval repeating again if our component needs to do periodic actions or cases like let's say our component will establish a websocket connection to backhand we will do them in the connected callback and when our component is gone from the screen we will clear those resources in disconnected callback and we have seen the attribute change callback usage in the button let's not repeat that here but let's focus to this last one this adapted callback this one does not have a very common use case this callback is triggered when this element is moved into a new document now let's show this to have multiple documents in a single page we can use iframe so here i'm going to add a new element right here and this is iframe and we are going to click the add it's going to be adding the app counter to this page and i'm just adding another button right here and this button is for moving the counter we will have on this page to inside this iframe so having another app button here and it has the text of move and when we click it it's going to be triggering this move function so let's implement the move here [Music] now first let's get the reference to the iframe so having my frame here and we will get it by document query selector with the element's name iframe [Music] and we are going to create a new document let's assign it as a variable here let's call it doc and we will create it by document implementation has this create html document method and it is taking the title let's say the title is new document now we are going to set the content of this iframe with the document we just created and for that we need to do like this let's say we will have a destination document test document variable and this iframe content document then we will run test document replace child [Music] with the first one is the new child and the second parameter is the old child the first the new child is the newly created dog so we will pass dog document element and the old child is dest document document element so we are creating this iframe we are creating a new document and we are replacing this iframes child with this newly created document now we will have a reference to our counter we are creating dynamically through this add method add function and then here we can just query it and get it like this documents query selector and it's going to be app counter and we can do like this we can call destination document body and we can append child to it [Music] and child and here we are going to call test document it has adapt node function and this function takes the element source so we pass counter to it so saving this one now we have this iframe on this page if we just take a look at here we have this iframe and it has another document right here so just changing the size here now clicking the add here we have the counter and clicking move and as you can see the counter is moved inside this this iframe and if we check the console logs let's do one more time clicking the add clicking the move and here we see the counter is moved and the account operation is done and if you check the the logs here the constructor the connected and this was the first time this item is added to our page then here the item is being moved to the new frame so first it's going it's calling this connected method so the interval stops there then it is calling this adapted this adapted callback is called then the after this element is adapted to this iframe again it is running this connected callback to to show it on the ui and again this is triggering the interval and it is going from where it left off so in such cases we can use this adapted callback function to do whatever needs to be done so we can just set the at the count the until we can reset the counter we can change the until or anything like that so if we summarize what we have practiced so far in constructor do not do anything about the dom this can be used to initialize the state value of this component and in connected callback we can do the dom related operations or we can start the repeating tasks in this method and in disconnected callback we are cleaning up the resources we are using and in attribute change callback this is triggered when the the attributes we are observing are changed and this adapted callback is used in the cases like we have right here so these are the life cycle methods and i'm going to clear this page a bit uh we are not going to use this iframe and we are not going to use this move buttons and removing corresponding function too so the current layout is like this we have the add and we have the remove functionalities next we will see the other functionalities of the elements by going on from this stage in our custom button element we have the attributes like this text and in progress each html element have multiple attributes the button element itself has the attributes like we are setting here disabled and the on click or the others now let's see how the actual button elements attributes are behaving differently when compared to our custom element attributes now let's use this chrome developer tools and let's play with the button element so we can get the button element like this we can run query through document and we will use the query selector method and we are going to query the button this is the actual element name this method is returning the first matching element we have two buttons here if we check it like this we have our custom app button and in it we have the the button and we also have the other app button which is for remove and we have the button in that one too so when we run the query we are selecting this one this specific button element so here let's assign it to a variable like this let's say this is the button and we are setting these buttons disabled attribute so let's try that one here so if we run button set attribute with the disabled set as true here the button is updated and here we are seeing the disabled style is also applied to that one and we can check the the value like this we can just run button disabled so this is this buttons property class property and here we are seeing it is true now if we run button remove attribute and let's remove the disabled here the style is changed back to the regular button and if we run button disabled like this here it is returning back false so this is happening because the disabled is not just the attribute of this button element but also it is class property and let's clear this part we can set the disabled through the set attribute but also we can run like this button disabled and we can assign the value true to it so here we are seeing the button is disabled now and if we check the elements right here here in this button we see this disabled attribute and just like setting it to true we can just set it to false like this and the button is back to the default style and if you check the button right here the disabled attribute is gone so when we do an update in one of them either we set the attribute or we set the property the change is reflected to the others let's also try the same thing for our custom element so let's get the element first let's say this is let's say this is app button fb instance and we will get it by document query selector and our element name is app dash button [Music] so if we set the attribute app b set attribute we are setting the attribute for our custom element of the in progress and this was triggering whole change on our component like changing the text changing the style of it and disabling the button so we will see that reaction right here we are setting in progress as true here the button is currently in in progress state but if we run just like we did for the button if we run app button in progress here we are receiving it is undefined or if we run app b in progress as false we see nothing about it so the class property methods are not working we can only update our component via the attributes so if we run f b remove attribute and we passed in progress to it here the button is back to the num progress state so to make this app button to work like the button in terms of the attribute and property synchronization we will add the setter and getter methods for our properties so the setter and getters are defined like this in javascript classes we can let's let's add it right here so this one is for setting and our function will be in progress and we will receive a value for this function let's call this is a progress and based on the value this can be true or false so if the progress is true [Music] in javascript we don't have to specify if it is equals to true the the value is either truthy or falsie so if it is true then we will be here in this if block so what we will do is we basically we will reflect the change to attributes and we do that by running this set attribute with we are going to set the attribute of in progress and we will set it to true and otherwise if the progress is not true so the else case here we will just remove that attribute from this custom element so saving this one now let's get the custom element once again in the console let's say it is fp and this is autocompleting our previous query right here so i have the app b app button and let's set the in progress as true and here we are seeing the button is currently in in progress so basically this in progress is this set method set function so we are passing this value through to it and based on this value we are setting the attribute the in progress to true and since the attribute is changed for this element this attribute is observed because we are telling we are observing this one in this method and this attribute change callback is called and then we are updating the inner button text content attribute and the class list so that's how it is working and if we go with the fb in progress i'm just trying to get the actual result and here it is saying undefined because we only have this set method for this property to have a get functionality we will add another one right here get in progress and basically we are going to return get attribute in progress saving it and running the same commands here fb in progress to true and if i type ap in progress now i'm receiving this through because of this function we have here and just like setting it to true we can set it to false to [Music] stop the progress so you may be asking why are we doing this why do we need both of them since this component is basically a class right here this is a class we can pass values to it through these properties for the element attributes they are only taking string values but for the custom class properties we can set any object we want attributes are useful for configuring the elements declaratively so here when we are adding it to right here like this we can set the in progress or other attributes so we would be declaring half this element to be behaving and also the apis like the accessibility and css selectors rely on to the attributes so reflecting a property to attribute is useful anywhere we want to keep the elements dom representation in synchronous with the javascript state of that custom element so a scenario would be like this let's say we will have a a new style for this button and just like this hover or disabled we can say let's define it here when this app button is having this attribute the attribute is in progress we can set it to something like this we can just set transform and let's scale this element and let's scale just 10 percent like this and for transformation we can set the origin to the top and left let's try this one so currently if we just click this one we are not doing any progress right here we are not setting this in progress so that's why nothing is applied but if we go here and get the button once again and we set the in progress to true here the button is scaled up and this style we defined right here is applied and if i go and set this value to false the button is shrink back to the original size or we can just update this implementation right here we can add a delay to appending this counter so what we can do here first let's get the button add button we will get the first one and we will get it by document query selector and we will get the app button and initially we will set this add button add button in progress to true [Music] then let's have a set timeout here and this is going to be running after two seconds and in this callback we are just going to create a counter and we will append to the body and let's say we will add button in progress will be false so saving this one and clicking the button here we are seeing the button is scaled and after that the in progress is gone and the counter is added so with this way we are setting the class property but since we are reflecting that change to element attribute our css here is applied to it it's not mandatory to do this but it's recommended implementation since an element can be added to document just like a regular html element or it can be added just like we did here through the javascript and when we have this instance access we can set the values any way we want we can go with the attribute or we can go directly assign the the property of the class so to support both of these use cases class properties should be reflected to the attributes now we have implemented our custom button and we built it by extending this html element instead of that one we could have extend the html button element so we can extend the built-in button so let's do that first we will replace this html element with html button element and we will update this defined part we were passing this element name and we were passing the class for that element but when we are extending the built-in ones we will add the third parameter here and that is taking an object and in this object we will tell this is extending the button now we can change the implementation we have here we can just replace this app button with selecting them so i selected them with the ctrl d in windows and changing them to just button and here i'm going to add another attribute and that attribute is so this button is app button and this is our element name so doing the same thing for the other one now let's save this and here we see the style is broken we have styled button inside regular button so the outer part is the the default button and the inner part is our custom button so this is happening because in this connected callback we are setting inner html to it so we are adding a button inside a button if we check the elements tab right here here we have button and in that button we have another button so that's why this is looking like this now since this is a button we no longer need to set its inner html so just commenting out this part now the button is looking like this now we have these buttons but they don't have any text in it so we are just seeing this part from the button since this is extending the the default button we can pass the text as a child to it just like we do for the button so let's say this is going to be add and the other one is remove so we have the add and remove buttons and also we will apply the the css classes the btn to this button so doing it for both of these buttons class is btn now we can see the button but if we click click it the functionality is broken and here we see the error because in this add functionality we are querying app button which is undefined so that's why it's broken so let's change this part we are getting the button not the app button so we are querying this one and let's save this and if i click the add here we have another problem the counter is visible but the style of the button is gone because again in this button implementation we are querying this element to get the button but now this is the button itself we no longer need to query it so we don't need this part and let's change this part to just this so this is the button and we are setting its text content we are setting its attribute and we are setting we are adding a class to it but there is one more thing we need to do here we are setting the text content through the attribute but we don't need to have this text attribute if we want to go with the button like this so instead of relying onto the text attribute we need to get the text content of the button let's get it right here so we were getting the text from attribute but now we can get the text and let's assign this to as a property for this class so this text let's say this text is this text content so we are copying this value to this property of this class and then here when we are in progress we are setting the text content to this value and after the progress is done we are going to revert back to the initial value and that initial value is now in this text property of this class so let's save this and let's click the button here it is showing the loading and it's going back to the ad and the functionality is properly working now by the way the button is not scaled anymore because the css we have here for specific to app button so if we just change to button it's going to work let's try that here it is scaled up and it's also overlapping to the remove button so this is how we can extend the built-in elements and we can add the functionality to them now we are extending the button capability but this functionality is not supported by old browsers it's working with chrome or working with the firefox opera or microsoft edge but this extend functionality is not supported by safari and we can check here in this page can i use dot com to see which browsers are supporting this functionality and if we highlight this part it is saying that it is supporting autonomous custom elements but not customized built-in elements so this is not supported by safari or ios safari or internet explorer 11 and we also have the other unsupported browser here but the green ones the edge firefox chrome opera and android browser these are supporting this web components this custom elements functionality now let's see how it is working with safari currently so we have this page so we are seeing this buttons they are visible and let's click the add so here we don't see any progress about the ongoing action but the counter is added and it is properly counting for resolving this behavior we can use polyfills polyfields are basically the functions the javascript codes which are simulating the functionality we are looking for so for custom elements we have polyfills and for custom elements like this specific case which is extending the built-in elements we have polyfills too so here in this page we have this polyfill it is showing the limitations or the use cases let's add this to our index.html so adding it right before our script we where we are defining our custom elements and let's try with this one again clicking the add button and now we are seeing the progress is properly shown so with the polyfills we can achieve the functionalities we are looking for and also there is this page this web components.org and it has this polyfills page they have the polyfills for the different apis of the web components so the actual source code is right here and we can get the the cdn uh or we can install that that components library to our local environment and use them as uh the node module in our project and here it is saying use there is this web components bundle js just import that one like this and then load your modules so it's going to be supporting the functionalities coming with the web components but again there are there are issues or there are missing parts here so it's not covering all the cases but it's covering most of the things we need for the web components so we add this polyfill to our index html and currently in chrome if i click the add button nothing is changed it's properly working so this polyfill is not breaking the existing functionality it is just checking if that functionality is built in this browser if it is not then it is just adding the functionality coming with the script otherwise it is just re discarded so that's how it is not affecting the behavior in the the the chrome and i'm not going to continue with this implementation i'm not going to extend the built-in elements so just removing this part changing everything back to my component so this was app button this was app button 2 and there is no need to add this is here and we also don't need to set the class and we have this text so we don't need to have a child right here and let's update these two as app button and we will update this part too this is going to be html element and just uncommenting this part and removing this text part and changing this part too and this is going to be the button [Music] and this is going to be again get attribute text like this so we changed everything back also let's remove this one from here we are just defining an element with the name and the class we are not extending the built-in button so saving this one and and we have one more thing right here we changed it back to we changed it to button but it's it's now app button so in progress we will have this style this scale up and we also need to update this part too we were querying the button because we changed this to just button but now it is f button and let's save this and here clicking the add and here the progress is visible and the button is scaled up and the functionality is properly working so that's how we can extend the built-in button and we can make it work with the safari
Info
Channel: Programming with Basar
Views: 101
Rating: 5 out of 5
Keywords:
Id: SNSXWeRuQ3A
Channel Id: undefined
Length: 99min 53sec (5993 seconds)
Published: Sat Sep 11 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.