Blog

Demystifying Web Components

By  
Ville Ingman
·
On Oct 7, 2014 7:00:00 AM
·

Incoming! We’ve got some cool stuff on the way: Web Components. This is so burning hot and awesome but it also generates a lot of hype and but-whats-in-it-for-me thoughts. I’m a Java guy - how can I use all this? If you are feeling the same, just read along.

Let’s clear this out for Java guys like you and me. In this blog post I’ll show you how to use Web Components in Java. First on the browser-side and then continuing to server-side. I tried my best to only use the minimum effort needed with minimal amount of work. After reading this you’ll have a good understanding of the foundation, on the basic building blocks you’ll need for actually using Web Components. Then you can get all smart and generic with your very own programming style and architectural desires. This article is continuing our previous efforts on the topic.

What are Web Components?

Are you ready? Here it comes: Web Components is all about getting encapsulation for web development. Finally. This approach is something Java people learn from day one. Create an object, have internal logic hidden behind a Java API, consume this object in your project. Web Components mean exactly the same thing on the HTML level but the terminology is a bit different. That’s it. Demystification done.

A Few facts to begin with

Web Components is a bleeding edge thing and browser support isn’t there yet. So don’t burn your fingers with it directly and just take the Polymer project. Period. These lads are doing a great job in providing a “web components” API for you. As browser support gets better and better, their wrapper implementation will get thinner and thinner. Meaning that you can use their API for your Web Components stuff until further notice. Nice.

You found a cool Web Component, how do you use it?

I was browsing customelements.io and found a simple and interesting QR code component. It looks like this:

And the HTML you need is as follows:

<qr-code data="My data stored as a QR code."></qr-code>

Really simple and really cool. You can give it any textual data and it’ll generate a QR code for you. Compliments to the author for this nice contribution.

So I thought it would be cool to create a simple app for generating vCards. Provide contact details, scan the QR code with your mobile phone and save the vCard that pops out. Simple and fun. This is how it turned out:

Try out the live app here. On the right you see the Web Component in action. It is a GWT widget that internally injects the needed HTML to the page: the <qr-code> tag and the needed HTML template import. The app itself is a simple GWT app. Wrapping this web component with GWT was amazingly simple. The diagram below shows the logical building blocks I ended up with:

The actual <qr-code> web component is described in the element descriptor qr-code.html. So this has to be available whenever the browser sees a <qr-code> element attached to the page DOM so that it knows what to do. The element descriptor qr-code.html contains all references to other resources it needs. In this case qr.js for its internal functionality and polymer.html. And before anything starts to happen we need to include the polymer library platform.js to our main HTML page.

The GWT app is implemented in class App.java. This is just plain old GWT programming and not really interesting in this context. Just putting the needed fields together and updating the QR code after each keypress. The whole project is available in Github. While building the layout, I simply create an instance of my custom widget QRContactWidget and add it to a layout. And whenever I have some new data from the user, I use QRContactWidget’s setter methods. See QRContactWidget source code below.

package org.vaadin.inki.qrgwt.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Widget;

/*
 * Widget that wraps a <qr-code> web component and provides a vCard setter API. 
 * Shows an QR code image on screen containing the given data. 
 */
public class QRContactWidget extends Widget {

    private static boolean injected = false;

    private String phoneNumber = "";
    private String email = "";
    private String lastName = "";
    private String firstName = "";

    /*
     * Constuctor. Ensures that needed html templates are added and 
     * injects a <qr-code> element to the page. 
     */
    public QRContactWidget() {
        super();
        ensureHTMLImport();
        Element el = DOM.createElement("qr-code");
        setElement(el);
        refresh();
    }

    /*
     * Injects the qr-code html template to page head section. 
     */
    private static void ensureHTMLImport() {
        if (!injected) {
            Element head = Document.get().getElementsByTagName("head")
                    .getItem(0);
            Element htmlImport = Document.get().createLinkElement();
            htmlImport.setAttribute("rel", "import");
            htmlImport.setAttribute("href", GWT.getModuleBaseForStaticFiles()
                    + "components/qr-code/qr-code.html");
            head.appendChild(htmlImport);
        }
    }

    /*
     * Sets all data and calls refresh to update qr-code image
     */
    public void setData(String first, String last, String email, String phone) {
        this.firstName = first;
        this.lastName = last;
        this.email = email;
        this.phoneNumber = phone;
        refresh();
    }
    
    /*
     * Sets the stored values in MECARD format to the <qr-code> element's 'data'
     * attribute that initiates the QR code image update
     */
    private void refresh() {
        String mecard = "MECARD:N:" + lastName + "," + firstName + ";EMAIL:"
                + email + ";TEL:" + phoneNumber + ";";
        getElement().setAttribute("data", mecard);
    }
}

Really simple. Two important things happen here:

  1. I create a <qr-code> tag and add it to the DOM; and
  2. I make sure that <qr-code> element descriptor’s HTML import is added to the page. This happens when <link rel=”import” href=”components/qr-code/qr-code.html”> is written to the page head section.

Afterwards whenever the data changes, you update the data-attribute value inside <qr-code> tag. This is all you need to do and the underlying web component takes care of all the magic for you. Just what I wanted.

The starting point App.html is practically empty as I do all the layouting in plain old GWT programming. I just have the needed GWT JavaScript inclusions and the inclusion of the platform.js that is provided by the Polymer Project:

<!doctype html>
<html>
  <head>
    <title>QR Code Widget Example</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <link type="text/css" rel="stylesheet" href="App.css">
    <script type="text/javascript" src="App/App.nocache.js"></script>
    <script type="text/javascript" src="platform/platform.js"></script>
  </head>
  <body>
  </body>
</html>

Done. You now have a Java version of a cool web component you can use in your GWT app. See resources in Github:

The server-side version

Ok, now we have the QRContactWidget client-side component. But I’d like to use this directly from my server-side Vaadin application as well. Let’s bring this to the server-side, Vaadin style.

Taking this to the server-side is really straightforward and basic “do your own widget for Vaadin” programming. We’ll re-use the widget class as-is (of course) and implement the following classes for wrapping all this as a server-side component:

In addition to this, we need to inject the platform.js to the main html page head section. The Vaadin style is to add a BootStrapListener to the Vaadin servlet. See the UI source code in Github: MyVaadinUI.java.

Conclusions

Now you know what you need to get going. Most likely you’ll change the approach to be a bit more generic. Maybe injecting platform.js only when needed. Maybe have a bit more complex Web Component wrapped where you start using JSNI for calling the Web Component’s JS API. And so on and so forth. Do also note that this is GWT 2.6 approach. The forthcoming JsInterop for GWT will make your life even easier. You should definitely check that out. A JsInterop preview is planned to come out with GWT 2.7 this fall and a stable release comes out with GWT 3.0. We’ve been playing around with it in this same context and the results look absolutely stunning. So go out there and have some fun. Be awesome!

Resources

Ville Ingman
Ville Ingman is one of the old boys in the Vaadin team. A true Vaadiner for over 10 years already. Sharing thoughts and interesting phenomenons from the Vaadin ecosystem. Stay tuned.
Other posts by Ville Ingman