You must have tried lot of ways to develop reusable components or widgets. But what about the components like "video", "audio" or "select" components (tags) of HTML(5)? Did you ever investigated how these components work without exposing its style, script or local DOM structure? Web applications are being developed in various ways depending on the requirements but hardly fulfill the reusability aspect across projects or modules.
This article would help upto a certain extent to create and reuse such type of web components which can be instantiated and reused in a similar way how we are instantiating and using other HTML elements.
About Web Components
Web component is a revolution in web application development. As stated for Introducing Web Components,
“Web components are a W3C specification to build a standalone component for web applications. It helps developers leverage the development process to build reusable and reliable component. This problem leads to component-based development.”
HTML provides a lot of built-in elements like video, audio, button, select, etc. These elements has its own properties, methods, attributes and CSS properties. It also allows to override its styles, but they are limited. Web components are something which allows us to develop our own custom elements which is similar to above elements or by extending above elements.
Each component has its own life cycle and encapsulated style, script and local DOM which allows interoperability of the components (HTML elements). These components can not only be reused across a single web application but can also be reused in multiple applications.
The Web component model is made up of four different specifications:
- HTML Templates – This contain markups that are consistent across web pages with the ability to inject dynamic content using JavaScript.
- Shadow DOM – This is designed to encapsulate DOM and CSS by hiding all child elements behind a shadow root. It defines functional boundaries between the DOM tree and the subtrees hide behind the shadow root. The following screenshot depicts the DOM structure of “video” tag.
- Custom Elements – This allows us to create our own custom elements with tailored DOM structure and ability to style and add behavior logic in our own way.
- HTML Imports – This allows us to import one HTML file in another HTML file. Using HTML Imports we can import and reuse HTML Templates for Web Components. The following is an example on how to use HTML Import to import HTML files:
<link rel="import" href="bower_components/paper-button/paper-button.html">
About Polymer
Polymer library, developed by Google, is a set of polyfills that help you create Web Components on all major modern browsers. It provides a easy-to-use framework for developing and instantiating custom elements in a simplistic fashion very similar to the HTML’s built-in elements like button, audio, video, etc.
Custom elements look like this:
- <google-map lat="37.790" long="-122.390"></google-map>
- <custom-gallery></custom-gallery>
As
stated in an article, Polymer helps us to develop and render custom elements by:
- Allowing us to create Custom Elements with user-defined naming schemes. These custom elements can then be distributed across the network and used by others with HTML Imports.
- Allowing each custom element to have its own template accompanied by styles and behaviour required to use that element.
- Providing a suite of ready-made UI and non-UI elements to use and extend in your project.
Installing Polymer
The recommended way to install Polymer is through Bower. So, prerequisites for installing Polymer through Bower are:
Bower is a package manager that manages dependencies for your project. If you are not familiar with Node.js and Bower, then it is recommended to read the instructions provided in respective URLs mentioned above to learn how to install and get started with it. It is not necessary to learn everything about Node.js and Bower but knowledge about installation and getting started with would be enough to install and work with PolymerJS.
Installing with Bower
Run this command from your project root folder using terminal:
bower init
This command creates bower.json file in the root folder of your project. The easiest way to create bower.json file is to press “enter” continuously for all the prompts after above command.
- bower.json looks like:
- {
- "name": "test-project",
- "version": "0.0.0",
- "license": "MIT",
- "ignore": ["**/.*", "node_modules", "bower_components", "test", "tests"]
- }
Zip package can be installed from polymerwebsite.
The next step is to install Polymer
bower install -–save Polymer/polymer#^1.2.0 By running above command in terminal, Bower adds a
bower_components/ folder in the root of your project and fills it with Polymer and its dependencies and updates
bower.json by adding:
- "dependencies": {
- "polymer": "Polymer/polymer#^1.2.0"
- }
Using Polymer’s Custom Elements
Polymer also comes with a rich, predefined set of elements that you can begin taking advantage of immediately. Using polymer’s custom elements in your document typically involves the four easy steps. The following is an example of how to download and use paper-button (one of Polymer’s custom element) in your application:
Step 1: Download the paper-button Custom Element package via Bower.
By running the following Bower Command in terminal, it will download all required files and folders to your project and add dependencies in bower.json file as well.
bower install -–save PolymerElements/paper-button
After running above command, dependencies section of bower.json looks like the following:
- "dependencies": {
- "paper-button": "PolymerElements/paper-button#~1.0.8",
- "polymer": "Polymer/polymer#^1.2.0"
- }
Step 2: Import Polymer’s “
webcomponents.js” and “
polymer.html”.
Add “
webcomponents.js” and “
polymer.html” (available in bower_components folder) to the
<head> of the index.html. Then you will be ready to use predefined custom elements in your documents.
- <script src="bower_components/webcomponentsjs/webcomponents.js"></script>
- <link rel="import" href="bower_components/polymer/polymer.html">
Step 3: Import the corresponding .html file in your document.
In this case, corresponding .html file refers to
paper-button.html that is generally located in bower_components folder (i.e. bower_components/paper-button/paper-button.html).
- <link rel="import" href="bower_components/paper-button/paper-button.html">
Step 4: Use the custom element markup anywhere in your document.
Like any other HTML element add markup of the custom element. Generally markup name is same as the .html file name. In this case:
<paper-button></paper-button> A huge list of predefined set of custom elements of Polymer is available at the Polymer official website (link mentioned in the reference section). It provides detailed documentation (in Docs section) with Demo. Bower command for each element is also available in “Bower Command” section in left panel.
Developing a New Custom Element using Polymer
Polymer library helps us to develop our own custom elements from scratch which can be assembled to develop new custom element, extended or reused across projects. Similar to HTML’s built-in elements, Polymer elements:
- Can be instantiated using constructor of custom element or document.createElement or adding markup in document.
- Can be styled with default styles of external CSS.
- Can have custom behavior logics can be defined using JavaScript.
- Support custom events handling on changing the attributes of the markup or any update in the values of the properties.
- Support data-binding
Register a custom element
A custom element can be registered by using Polymer function of Polymer library and passing prototype as parameter to it.
There are few specifications to define a custom element:
- It is necessary that the custom element has a property in the prototype
- There should be an id attribute in the <dom-module> tag.
- And value of id, is and name of the custom element file must have same value to work the custom element properly.
- And this value must contain a dash (-). In this case, it is hello-world.
For example:
- <dom-module id="hello-world">
- <template>
- <style>
-
- </style>
- <!-- Local DOM structure starts here -->
- <div>
- <h1>{{proName}}</h1>
- <!-- Data binding -->
- </div>
- <!-- Local DOM structure ends here -->
- </template>
- <!-- JavaScript goes here -->
- <script>
- var MyElement = Polymer(
- {
- is: "hello-world",
- properties:
- {
- propName:
- {
- type: String,
- value: "Hello World!"
- }
- }
- })
- </script>
- </dom-module>
The Polymer function registers the element with the browser and returns a Constructor which can be used to create new instances of the custom elements dynamically. For example:
- var el = new MyElement();
- document.body.appendChild(el);
LifeCycle callbacks
A good understanding of the Web components life cycle will enable you to build better applications and optimize the code. For example, if you need to ensure that some code runs before the DOM attached to document, you need to know where to place the code for that event.
So when we instantiate or remove any Web component, the following functions are called during the lifecycle:
- Created
- Ready
- AttributeChanged
- actoryImpl
- attached
- detached
Sequence of the callbacks as it is listed above.
facotyImpl method will only be invoked if the element is instantiated using Constructor (see below for instantiation options).
attributeChangedmethod will be invoked whenever any attribute is changed. It gets called after ready if there is any default properties set using “properties” object or “hostAttributes” object of Polymer prototype. It also gets called if any attribute gets changed dynamically.
Instantiation of Custom Element
Instances of Custom element can be done in multiple ways:
- Using document.createElement
- var el = document.createElement('hello-world');
- document.body.appendChild(el1);
- Using tags in HTML,
- <hello-world></hello-world>
- Using append of jQuery,
- $("body").append("<hello-world></hello-world>");
- Using Constructor,
- var el = new MyElement();
- document.body.appendChild(el);
Properties Declaration
Properties for the custom elements should be declared in the properties object of the prototype as shown below:
- var MyElement = Polymer(
- {
- is: "hello-world",
-
- properties:
- {
- firstName: String,
- lastName: String,
- age: Number,
- userName: "abcd",
- details:
- {
- propName1:
- {
- type: String,
- value: "Hello"
- },
- propName2:
- {
- type: String,
- value: "World"
- }
- }
- }
- })
The properties object supports some keys for each property. Few of the keys are:
- Type: type of the property i.e. String, Number, Boolean, Date, Array or Object etc.
- Value: Default value can be set here
- Notify: Type: boolean. If `true`, the property is available for two-way data binding. In addition, an event, propertyName-changed is fired whenever the property changes.
- Observer: Value is provided in the form of String and interpreted as methods which fires on change of the value of the property.
How to change value of properties from outside the component:
Value of properties can be changed by using query selector and .propertyName. For example:
- $("#myElement").propertyName = "xyz";
Data-binding
Data-binding in Polymer is a process of automatic data synchronization between model and view. For this synchronization, Polymer provides ability to bind properties to local DOM of the custom elements.
A binding is created with a binding annotation (i.e. {{ }} or [[ ]]) in the host elements local DOM template. Here is an example of data-binding using curly braces:
- <dom-module id="hello-world">
- <template>
- <style>
-
- </style>
- <div>
- <h1>Hello <span>{{firstName}}</span><span>{{lastName}}</span>!</h1>
- <!-- Data binding -->
- </div>
- </template>
- <script>
- var MyElement = Polymer(
- {
- is: "hello-world",
- properties:
- {
- firstName: String,
- lastName: String
- }
- })
- </script>
- </dom-module>
<hello-world first-name="Sumant" last-name="Mishra"></hello-world> Data-binding in Polymer is not very similar as in Angular. There is a significant difference in the way how Polymer handles data-binding and how Angular handles data-binding. For example, unlike AngularJS, each binded property needs to be wrapped with an element (span in above example). Two properties can not be declared in one dom element.
References
Polymer site nails more detail about data-binding. Please visit:
That’s all! For further reading on Web Components and Polymer, I would suggest to refer:
Thanks!