TQ
dev.com

Blog about software development

Subscribe

A tiny polymer clone: w3component.js

11 Apr 2016 - by 'Maurits van der Schee'

I like the idea of web components in a web application. I think it well-suited for things like menus, lists and forms. I especially like the concept of having three separate files for each element on your page. Much like this 3-layered MVC separation in back-end applications. You can have a similar separation in the front-end:

  1. HTML file holding a component's template
  2. CSS file holding the component's styling
  3. JavaScript file holding the component's logic

I wrote a tiny library, inspired by Polymer, to support this component separation. It is named "w3component.js" and you can find the code on Github.

The page

The page contains a web component reference. The "w3component" attribute may be prefixed by the component path:

<div class="w3component" data-src="hello-world">Loading...</div>

It is important that you load the following dependencies:

<script src="handlebars.min.js"></script>
<script src="zepto.min.js"></script>
<script src="w3component.js"></script>

Where Handlebars is the templating engine of choice and Zepto is a light-weight jQuery compatible library.

The 3 layers

Now the script 'w3component.js' will scan the html for divs with class "w3component" and then load three files based on the component name (in the custom "w3component" attribute):

The HTML in 'hello-world.html' looks like this:

<form><p>Hello <input name="world" value="{{world}}"></p></form>
<h3><b>Hello {{world}}</b></h3>

The CSS in 'hello-world.css' looks like this:

.w3component h3 { color:silver; }
.w3component form { margin: 0; padding: 0; }

The JavaScript in 'hello-world.js' looks like this:

w3component.components['hello-world'] = function (element, template) {
    var self = this;
    var state = {};
    self.submit = function(e) {
        e.preventDefault();
        state.world = $(this).find('input[name="world"]').val();
        self.render();
    };
    self.render = function(data) {
        element.html(Handlebars.compile(template)(state));
    };
    element.on('submit','form',self.submit);
    self.render();
};

Together they form the component that renders an input field that you can submit and that will update the H3 title.

Why not Polymer

What turned me off about Polymer is that it is trying to redefine how the web works. I'm not against it, but we are not there yet. This means a lot of "polyfills" are used to simulate browser features. In my opinion the users should not suffer from slow loading, because a front-end developer feels that there is a better way that the web should work. That's why I tried to copy the concept of component structure, while leaving all the other stuff out (33 lines of code, 1kb).

Edit 2016-04-20: Added vanilla JavaScript implementation to the repository.

Links