Build Your Own JavaScript Micro-Library Using Web Components: Part 3 of 4
Here is Part 3/4 of our tutorial series on building a JavaScript micro-library for creating your apps with Web Components. As I pointed out in previous lessons, the micro-library eases the path to development with Web Components, automating a lot of the work so developers can build their apps faster. Here's what we covered so far: Now in this tutorial, Part 3, we will automate another piece of functionality for classes that use our decorator. In this case, we'll automatically attach a Shadow DOM to those classes so that the user of the library does not have to manually create a Shadow DOM for their custom elements. Now that we have ElementMeta stored on the prototype of any class using the Component decorator, our next step is to write a reusable function that'll be used in the constructor of the same class to instantiate the Shadow DOM. By abstracting this logic to a reusable function , we'll reduce several lines of code in each component implementation down to one line. Basically, we want to take something like this... ...and reduce it to one line. The first argument of attachShadow is the instance of the class which, in the constructor , you can reference as this . The second argument is the Object that configures the call to element.attachShadow . You can read more about element.attachShadow on MDN . To start development of this new function , make a new directory named template in packages/common/src and create a new file in that directory named index.ts . Create another file in the directory, named shadow.ts . In packages/common/src/template/shadow.ts , create a new function named attachShadow and export it. Declare two arguments for attachShadow : context and options . Make options optional with ? and type define context as any , and options as ShadowRootInit , a type definition exported from lib.dom.d.ts . Follow up in packages/common/src/template/index.ts and ensure attachShadow is exported for the main index.ts . Finally, in packages/common/index.ts , export the attachShadow function. Jumping back to packages/common/src/template/shadow.ts , fill in the algorithm for attachShadow . Make a const named shadowRoot , type defined as ShadowRoot , equal to context.attachShadow . On the next line, make a const named template , equal to document.createElement('template') . This line creates a new HTML template. Set the content of the HTML template using the ElementMeta stored on the prototype of whatever class will use this attachShadow function. Pass in context.elementMeta.style to a style tag and context.elementMeta.template afterward. Finally, append a clone of the HTML template to the ShadowRoot . When you are finished, the attachShadow function should look like this: With Component and attachShadow now supporting autonomous and form-associated custom elements, you can now use the new decorator pattern in actual components. Build the @in/common package again so files inside the @in/ui package can pick up the latest changes. We're almost done building this Web Components micro-library, though there's a lot more features you could add. In the final lesson in building our micro-library, we'll refactor some example components to use the micro-library so you can see how end developers actually use the library. For more about building UI Libraries using Web Components, check out our latest book Fullstack Web Components: Complete Guide to Building UI Libraries with Web Components.