Tech notes for polymer


PolymerJS: Binding properties to DOM attributes & styling

We saw previously that we could set a custom element's property and have that value changed in the DOM.

In that case, we set a boolean and <span>{{warning}}</span> changed. That is, the DOM changed.

However, if we want to bind a variable to an attribute, <div warning="{{warning}}">hi</div>, then the DOM won't automatically change when the property does, although the underlining javascript value will.

So we have to use the <div warning$="{{warning}}">hi</div> syntax instead to change the DOM attribute. If we combine this with some CSS selectors, we can use it to style the element.

div {
    background-color: pink;
}
div[warning] {
    background-color: red;
}

Notes:

  1. If you open up the DOM inspector, you can see the attribute change when the property does, in the example below.

Full source: an-ele.html

<link rel="import" href="bower_components/polymer/polymer.html">
<dom-module id="an-ele">   
    <style>
        div {
            background-color: pink;
        }
        [warning] {
            background-color: red;
        }
    </style>
    <template>
        <div warning$="{{warning}}">hi</div>
    </template>
    <script>
        Polymer({
            is: "an-ele",
            properties: {
                warning: {
                   type: "Boolean"
                }
            }
        });
    </script>
</dom-module>

Full source: index.html

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
        <link rel="import" href="bower_components/polymer/polymer.html">
        <link rel="import" href="an-ele.html">
    </head>
    <body>    
        <template id="app" is="dom-bind">
            <an-ele warning="{{warning}}" on-tap="clicky">
            </an-ele>
        </template>
    </body>
    <script>
       window.addEventListener('WebComponentsReady', function(e) { 
            var t = document.querySelector('#app');
            t.clicky= function(e) {                
               var t = Polymer.dom(e).localTarget;
               t.warning = !t.warning;
            };
       }
    </script>
</html>
polymer polymer-styles polymer-properties

PolymerJS: Communicating between elements

We've learnt how to set custom properties on custom elements.

But we may want to communicate data between the host element and the custom element. We can use a property on the custom element for this.

In the host document, index.html in this case, we'll have a script tag that sets a property on a 'dom-bind' template called 'warning'.

window.addEventListener('WebComponentsReady', function(e) { 
    var t = document.querySelector('#app');
    t.warning = true;
});

Now in our template code in index.html we'll reference the {{warning}} property and also pass it to our custom element.

<template id="app" is="dom-bind"><div>{{warning}}</div>
  <an-ele warning="{{warning}}" on-tap="clicky"></an-ele>
  ...
</template>

Now in our custom element, set an on-tap event listener and change the value of 'warning' in that.

...
<template><div on-tap="clicky">hi</div>
</template><script>
    Polymer({
        is: "an-ele",
        properties: {
            warning: {
               type: "Boolean",
               notify: true
            }
        },
        clicky: function() {
            this.warning = !this.warning;
        }
    });
</script>
...

Note the notify property that's been added to the 'warning' property. This makes sure any changes to 'warning' in the element bubble up to the hosts, our template in index.html for example.

Now when we tap on the div in our custom element, the value in index.html will automatically update.

Note:

  1. Although we're only communicating between index.html and the element, it's trivial to communicate between two elements -- in this case you'd just bind the 'warning' property to another custom element.

Full source: an-ele.html

<link rel="import" href="bower_components/polymer/polymer.html">
<dom-module id="an-ele">
    <template>
        <div on-tap="clicky">hi</div>
    </template>
    <script>
        Polymer({
            is: "an-ele",
            properties: {
                warning: {
                   type: "Boolean",
                   notify: true
                }
            },  
            clicky: function() {
                this.warning = !this.warning;
            }
        });
    </script>    
</dom-module>

Full source: index.html

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
        <link rel="import" href="bower_components/polymer/polymer.html">
        <link rel="import" href="an-ele.html">
    </head>
    <body>

        <template id="app" is="dom-bind">
            <div>{{warning}}</div>
            <an-ele  warning="{{warning}}"> </an-ele>
        </template>
    </body>
    <script>
       window.addEventListener('WebComponentsReady', function(e) { 
            var t = document.querySelector('#app');
            t.warning = true;
       });
    </script>
</html>
polymer polymer-communication polymer-properties

PolymerJS: Usage of element.updateStyles()

The shim used for CSS variables is lightweight.

This means you have to use element.updateStyles() in places where you'd like it to be automatic.

We've seen we need to use it if we dynamically update a CSS variable using element.customStyle.

Additionally, in a custom-style in index.html for example, if you have a style that changes a CSS variable based on a class selection:

an-ele {
    --an-ele-name-bgcolor: green;
}
an-ele.warning {
    --an-ele-name-bgcolor: warning;
}

Then, without updateStyles(), nothing will happen if add or remove the 'warning' class from 'an-ele'. If you want to want to see the change you need to call element.updateStyles().

However, if instead you define two CSS variables in your custom element, and change the class at runtime, then it will work:

Within your custom element's style tag:

:host {     
    background-color: var(--an-ele-name-bgcolor, white);
}
:host.warning { 
    background-color: var(--an-ele-name-bgcolor-warning, white);
}

Within your index.html custom-styles style tag:

an-ele {
    --an-ele-name-bgcolor-warning: red;
    --an-ele-name-bgcolor: purple;
}

Then changing the 'warning' class at runtime will work without a call to updateStyles(), since the css variables shim no longer needs to change a CSS variable at runtime.

polymer polymer-styles

PolymerJS: Event retargeting in Polymer 1.0

Event retargeting makes an event from a custom element look like it's coming from the overall custom element tag, as opposed to an element within.

For example:

<dom-module id="an-ele">
    <template>
        <span on-click="clicky">hi</span>
    </template> 
...

An event from the span tag would be retargeted to come from the 'an-ele' tag when it bubbles up to a parent listener.

Event retargeting was part of ShadowDOM. But the more performant ShadyDOM -- the default in 1.0 -- does not have this.

But Polymer.dom(e).localTarget will retarget an event object for you to the overall tag.

Given a custom element in index.html which has a on-tap listener, this method on the dom-bind template will give you to retargeted event:

t.clicky= function(e) {
    var t = Polymer.dom(e);
    console.log("retargeted:", t);
    console.log("normal:", e);
}

Giving the output:

retargeted: Polymer.EventApi.EventApi {event: (...), rootTarget: (...), localTarget: (...), path: (...)}
normal: CustomEvent {detail: Object, ....

Full source: index.html

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
        <link rel="import" href="bower_components/polymer/polymer.html">
        <link rel="import" href="an-ele.html">
    </head>
    <body>
        <template id="app" is="dom-bind">
            <an-ele on-tap="clicky">
            </an-ele>
        </template>
    </body>
    <script>
      var t = document.querySelector('#app');
      t.clicky= function(e) {
          console.log("retargeted:", Polymer.dom(e));
          console.log("normal:", e);
      };
    </script>
</html>

Full source: an-ele.html

<link rel="import" href="bower_components/polymer/polymer.html">

<dom-module id="an-ele">
    <template>
        <span>hi</span>
    </template>
    <script>
        Polymer({
            is: "an-ele"
        });
    </script>    
</dom-module>
polymer polymer-events

PolymerJS: Allow custom elements to be styled: many rules with mixins

Previously, we showed how one CSS property in your custom element could be styled from the outside using a shim for CSS variables.

But we often want to allow the user to style not just one rule for a class, not even many, but anything for that class.

Polymer 1.0 uses an experimental feature called mixins that allows the element user to specify any CSS property for a class.

We @apply(--an-ele-name-theme) in CSS selector for the class in the custom element:

<dom-module id="an-ele"><style>
        .name {
            @apply(--an-ele-name-theme);
        }
    </style>
...

Then in the index.html, or hosting custom element, we specify the --an-ele-name-theme under the selector for our element, and add the styles there.

<style is="custom-style">
    an-ele {
        --an-ele-name-theme: {
            display: block;
            color: white;
            font-weight: bold;
            background-color: blue;
        };
    }
</style>

Notes:

  1. is="custom-style" is only needed if your styling the element from index.html not a polymer element.

Full source: an-ele.html

<link rel="import" href="bower_components/polymer/polymer.html">

<dom-module id="an-ele">

    <style>
        .name {
            @apply(--an-ele-name-theme);
        }
    </style>
    <template>  
        <span class="name">hi</span>
    </template>
    <script>
        Polymer({
            is: "an-ele"
        });
    </script>   

</dom-module> 

Full source: index.html

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
        <link rel="import" href="bower_components/polymer/polymer.html">
        <link rel="import" href="an-ele.html">            
        <style is="custom-style">
            an-ele {
                --an-ele-name-theme: {
                    display: block;
                    color: white;
                    font-weight: bold;
                    background-color: blue;
                };
            }
        </style>
    </head>
    <body>
        <an-ele>
        </an-ele>
    </body>
</html>
polymer polymer-styles

Page 2 of 4
prev next
Click me