What is polymer

Polymer is a framework for creating web components. Polymer is different than other web frameworks in that it only exists while browsers catch up on implementing the web components specification(which hasn’t been finalized).

Polymer doesn’t do much in helping you create single page apps. It doesn’t have a router, tools for internationalization or a nice abstraction for XMLHttpRequest. The way you build apps using polymer is by creating components that help you do those things.

Lets play

The best way to get to know polymer is to start using it. Start by creating a folder for the app and add a bower.json file. My file looks like this:

1
2
3
4
5
6
7
8
9
10
11
{
  "name": "polymer",
  "version": "0.0.0",
  "authors": [
    "Adrian <mymail@something.exe>"
  ],
  "license": "MIT",
  "dependencies": {
    "polymer": "~1.0.2"
  }
}

Now, our index.html:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- This file contains polyfills that allow web components to work
   in browsers that are not capable of handling web components by their own.
   When browsers implement the web components specification this file shouldn't
   be needed anymore -->
    <script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
    <!-- Load my component -->
    <link rel="import" href="ncona-component.html">
  </head>
  <body>
    <!-- Use my component -->
    <ncona-component></ncona-component>
    <!-- Some other html in the page -->
    <a href="http://ncona.com/">Visit my blog</a>
  </body>
</html>

This is how ncona-component.html looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- We need this in order to use polymer's syntactic sugar -->
<link rel="import" href="bower_components/polymer/polymer.html">

<!-- Component definition -->
<dom-module id="ncona-component">
  <!-- These styles only affect this component. You can use a selector that
  is as general as you want and it won't affect other element in the DOM -->
  <style>
    a {
      color: #f00;
    }
  </style>
  <template>
    <a href="http://ncona.com/">Visit my blog</a>
  </template>
</dom-module>

<script>
  // Declare component. Here we specify that we are going to use the custom tag
  // ncona-component for this component. From now on, whenever there is a
  // <ncona-component> in the DOM, it will become an instance of this component
  Polymer({
    is: "ncona-component"
  });
</script>

The final result is this:

ncona-component

I added a link to show how the link inside the component is red, but the link outside the component is not affected even when the CSS rule targets all a tags.

That is a pretty simple example, but not very useful. When you design a web component you give the users of your component an API to configure and interact with the component. Lets design a little component and then build it with polymer.

Advanced example

The name of the component will be ncona-accordion. It will work like this:

1
2
3
4
5
6
7
8
9
10
<ncona-accordion ncona-allow-all-closed>
  <ncona-element>
    <ncona-title>Something</ncona-title>
    <ncona-content>Some content</ncona-content>
  </ncona-element>
  <ncona-element ncona-selected>
    <ncona-title>Something</ncona-title>
    <ncona-content>Some content</ncona-content>
  </ncona-element>
</ncona-accordion>

The ncona-allow-all-closed property makes it possible for the user to close all elements of the accordion. You can also specify one of the elements as ncona-selected. This will initialize the accordion with that element selected.

This is a heavily commented version of the polymer component:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<link rel="import" href="bower_components/polymer/polymer.html">

<dom-module id="ncona-accordion">
  <style>
    /* When using content interpolation with polymer you need to use ::content
       to style the interpolated content. To avoid your styles to leak to the
       outside DOM you need to wrap the interpolated content and use it in the
       css selector. */
    w ::content ncona-title,
    w ::content ncona-content {
      display: block;
      border: 1px solid #000;
    }

    w ::content ncona-title {
      cursor: pointer;
      background: #ddd;
      /* This allows the users of this component to customize certain aspect
         of this component. For this particular component we only allow the
         user to change the background of the title */
      background: var(--ncona-accordion-title-color);
    }

    w ::content ncona-content {
      display: none;
    }

    w ::content ncona-element[ncona-selected] ncona-content  {
      display: block;
    }
  </style>
  <!-- We are using <content> to copy all the content from the light DOM (The
  outside DOM) into the local DOM (shadow/shady DOM). We use a wrapper so we
  can style the interpolated content without affecting the outside -->
  <template><w><content></content></w></template>
</dom-module>

<script>
  Polymer({
    is: 'ncona-accordion',
    // Allows mapping between element attributes and properties of component
    properties: {
      // If this is true, then all elements in the element can be closed
      nconaAllowAllClosed: Boolean
    },
    listeners: {
      // When the element is clicked, execute handleClick
      click: 'handleClick'
    },
    handleClick: function(e) {
      // We only care if a title was clicked
      if (e.target.tagName !== 'NCONA-TITLE') {
        return;
      }

      // Get the current status of the clicked element and save it for later
      var elementStatus = e.target.parentNode.getAttribute('ncona-selected');

      // Mark all elements as unselected
      var elements = this.querySelectorAll('ncona-element');
      for (var i = 0; i < elements.length; i++) {
        elements[i].removeAttribute('ncona-selected');
      }

      // Only show it if it was not being shown before when allowAllClosed set
      if (!this.nconaAllowAllClosed || elementStatus === null) {
        e.target.parentNode.setAttribute('ncona-selected', 'ncona-selected');
      }
    }
  });
</script>

We can see the accordion on the page and working as expected:

accordion

A cool thing about the accordion is that we made it possible for the user to change the color of the titles. The user can add this style declaration:

1
2
3
4
5
6
7
<!-- you have to include the is="custom_style" for polymer to recognize this
style declaration -->
<style is="custom-style">
ncona-accordion {
  --ncona-accordion-title-color: red;
}
</style>

And the title color will change:

accordion-styled

A lot of the features that I used in my examples require polymer 1.0. If you are using an old version of polymer, they might not work.

[ design_patterns  dom  javascript  polymer  programming  ]
Mutexes in C++ design_patterns programming
Passing by reference to a thread in C++ design_patterns programming
Sorting algorithms javascript programming
Futures, async, packaged_tasks and promises in C++ design_patterns programming
C++ Header files  design_patterns programming