Let’s say, you want to develop a new web application. An important step in your technical conception is the choice of an UI - library. Beside SAPUI5, there are a vast number of great UI frameworks and technologies, so it’s quite complicated to keep an overview.
But almost all of these frameworks have conceptual insufficiencies, especially when you want to develop encapsulated, re-usable elements. Just have a look at a part of the HTML markup of the SAPUI5 ListBox control:
As you can see, all single elements of the control are exposed. This behavior leads to the following problems:
Besides, the SAPUI5 ListBox is only re-usable within a SAPUI5 application. When you create an application with e.g. angular.js, it’s not possible to integrate a single control of the SAPUI5 library. Instead, you need to include at least the core framework to use its controls. The actual problem is, that nearly all UI - frameworks use different approaches for control development and implementation. They don’t use a common standard for components. And that means, they don’t work together.
This is where Web Components comes in. The following graphic illustrates the role of this new technology.
The layer „Web Components“ provides real encapsulated, re-usable building blocks. It’s the new basis for frameworks and applications.
Enough theory! Let’s have a look at the code. Web Components consists of these four technologies (although each can be used separately):
I’m going to show you in this post, how to create a simple Web Component. All what you need is a text editor, a Web Server and Google Chrome. At first, create a new HTML site with the following markup in your web servers root or project directory.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Web Components</title>
<style type="text/css">
a{
color: #0f0f0f;
}
</style>
</head>
<body>
<a href="#">Standard Link</a>
</body>
</html>
When you look at this site in your Chrome, you will see a simple link. Now, our goal is to develop a custom button element, which uses internally an "a" element. The result is attached at the post.
HTML Imports are something like a packaging mechanism for Web Components. When you want to use a Web Component in your HTML-site, just import it! Create the HTML-File "custom-button.html" and refer to it from your index.html. Place this code at the end of your "head" section.
<link rel="import" href="custom-button.html">
We are going to implement the component-related markup and coding in our "custom-button.html".
Of course, we want to render some HTML and Styles for our element. To do this, we place our markup and CSS into the new HTML template element. It’s important to know, that content in this tag will not be rendered when the page is loaded. The application itself needs to do this with some additional steps via JavaScript. Switch to the "custom-button.html" and add the following markup:
<template id="custom-button-template">
<style>
a{
display: inline-block;
border-radius: 2px;
padding: 10px 25px;
color: #fff;
background-color: #6083c2;
text-decoration: none;
transition: background-color .25s;
}
a:hover{
background-color: #345288;
}
</style>
<a></a>
</template>
We also want to create our own custom HTML tags and elements. Besides, we need something like lifecycle callbacks, so we can execute coding in different states of the element. "Custom Elements" provides us these features. The following callbacks are currently available (see MDN😞
Let’s place a new custom element in our index.html (beneath the "a" element) and add some attributes:
<custom-button text="Click me!" href="#"></custom-button>
When you define a custom element, you must always use a hyphen in the name of the control! After that, we need a little bit JavaScript to describe our element and register it. In your "custom-button.html" paste the following coding beneath the "template" section.
<script type="text/javascript">
(function() {
// get a reference to the document element of the current script.
// we need this later in our example
var importDoc = document.currentScript.ownerDocument;
// create a prototype for the new element.
// basis is the common HTMLElement Interface
var CustomButtonProto = Object.create(HTMLElement.prototype);
// implement a lifecycle callback
CustomButtonProto.createdCallback = function(){
// todo
};
// registers the new custom element in the browser
document.registerElement("custom-button", {prototype: CustomButtonProto});
})();
</script>
This is one possible approach for creating and registering a custom element. You can create the prototype of your new element in different ways. But i think, this one is pretty clear. Besides, it’s also possible to base a custom element on a native element like "a". In other words, you can inherit from native controls. Such an element has a different tag syntax and looks like this <a is="my-anchor">.
Shadow DOM is the key for encapsulation the JavaScript, CSS and templating in a Web Component. With this technology, we are able to separate our component specific code from the rest of the page. Let’s see, how it works. This is the implementation of our createdCallback method for the custom element.
CustomButtonProto.createdCallback = function(){
// select the template element
var template = importDoc.querySelector("#custom-button-template");
// get the attributes of our custom element and transfer the values
// in our template
template.content.querySelector("a").innerHTML = this.getAttribute("text");
template.content.querySelector("a").href = this.getAttribute("href");
// create a copy of the templates content, so we can place it in the current document
var clone = document.importNode(template.content, true);
// insert the content to the existing element(this reference) via shadom dom
this.createShadowRoot().appendChild(clone);
}
Now we are done. When you open the index.html in your browser and inspect the markup of your custom element, you should see something like this:
The section „#shadow-root“ proves, that the implementation of our control is encapsulated.
Because our custom element is nothing more than an ordinary HTMLElement, we can treat it like a normal element. So you can add eventlisteners, query it etc.
It’s important to understand, that a Web Component can be „viewless“, so it just contains logic. This concept should be well known for all Web Dynpro developers (model/viewless WD-Components). The idea behind Web Components is the creation of elements for all kinds of use cases.
Good Bye SAPUI5, Hello Web Components? No, and there are several reasons for this.
In my opinion, Web Components are going to play a major role in future web development. Currently, i recommend to just observe this technology. When the browser support gets better and more projects like Polymer exists, then it’s really time to start with Web Components.
Sources:
WebComponents.org - A place to discuss and evolve web component best-practices
Web Components - Mozilla Developer Network
Google I/O 2015 - Polymer and modern web APIs: In production at Google scale
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
37 | |
10 | |
5 | |
4 | |
4 | |
3 | |
3 | |
3 | |
2 | |
2 |