polymer Reusable Toolbar with Modal | Share | Fork icons - Coding the element


Example

So far, we defined how easy it is to write a custom element that hides the messy html behind it and gives the user, an easy to write and brief markup.

Time to code it!

Our custom element, to display the bar below the hero image should

  • Accept a Link to be shared
  • Accept a Link to the Repo to be forked
  • Accept a modalId to differentiate between other Modals.
  • Accept a Title for the Modal

Register the tool bar custom element with Modal | Share | Fork icons

Let us register our custom element, that accepts the above list of properties.

<script>
Polymer({
    is:"tool-bar",
    properties:{
        link2Share:{
            type:String,
            value:""
        },
        link2Fork:{
            type:String,
            value:""
        },
        modalId:{
            type:String,
            value:""
        },
       title:{
            type:String,
            value:"myModal"
        }
    }
});
</script>

Very nice! Next, add the Html we need.

First up, The icons for Modal/Share/Fork need to be added.A simple ul will do.Also,we’ll be using, Polymer’s iron icons for displaying Modal/Share/Fork icons.

Note: Iron Icons from Polymer

Install the icon sets like so, in the root of your project.

bash $ bower install --save PolymerElements/iron-icon

bash $ bower install --save PolymerElements/iron-icons

Next, Include the installed Polymer elements in the custom element declaration, like so

Note:

For all practical purposes, our custom element, will be lodged inside

Project-root/elements

<link rel="import" href="../bower_components/iron-icon/iron-icon.html">
<link rel="import" href="../bower_components/iron-icons/iron-icons.html">
<link rel="import" href="../bower_components/iron-icons/social-icons.html">

Very Nice! If you are wondering how to use iron icons, see the note below.

Note: Iron Icon usage and Grammar

If we need to use the info icon for our Modal Popup, we write the markup like so:

<iron-icon icon="icons:info"></iron-icon>

If we want the social networking share icon, then the icon attribute above, becomes

icon=”social:share

So the grammar meaning, I need the iconset from “SOCIAL” and I want the SHARE icon from that set.

You can alternatively, use font-awesome , in which case, you can use,

choose what you deem best fit.

Once the includes are done,we write the template for our custom element. We will be using one way binders for data in our custom element’s markup.We bind whatever is passed as attributes by the user, to their corresponding properties of our element, while embarking on our element’s registration call.

So the html blueprint for our custom element is:

<dom-module id="tool-bar">
 
    <template id="tool-box">
 
        <ul class="flex-wrap toolbar">
            <li>
                <iron-icon icon="icons:info" id="anchor-for-[[modalId]]" onclick="clickHandler(event)"></iron-icon>
            </li>
            <li>
                <a href="https://plus.google.com/share?url=[[link2Share]]" target="_blank" ><iron-icon icon="social:share"></iron-icon></a>
            </li>
            <li>
                <a href="[[link2Fork]]" target="_blank"><i class="fa fa-2x fa-code-fork" aria-hidden=true></i></a> 
            </li>
        </ul>
 
    </template>
 
</dom-module>

Cool! So the tool bar has its templated ul , which lists the three links

  • info icon – Modal Popup
  • share this icon – share on google
  • Fork this icon – Fork the repo

Also, we have bound the attributes the user writes, to the respective properties.

Note: Making the Modal ID unique

We have addressed uniqueness of the info icon, by specifying the id attribute like so

id="anchor-for-[[modalId]]" onclick="clickHandler(event)"></iron-icon>

So each Project, will have a unique anchor id.

i.e,

If the user passes “project-cats” as modal-id, in the call to our custom element, the anchor id would be “anchor-for-project-cats”

If the user adds another project, and passes “project-puppy” as the modal-id attribute, the anchor id would be anchor-for-project-puppy

and so on.

But How do we ensure, each info icon is mapped to its own Modal?

The “iron icon“ for info, should be assigned a “data-dialog” attribute, which needs to be unique as well.

The data-dialog attribute, is similar to the data-target attribute in the bootstrap modal.It needs to be unique for every new Project.

We leave it to the user, to maintain uniqueness. So the user can not have the same modal-id attribute for different <tool-bar> calls.

So as the note above states, we need to map each Project’s info icon, to a data-dialog.

Let us add that functionality.

We use the ready method.It is very similar to Jquery’s

$.ready();

.It is invoked, when the custom element , is finished loading.

Add this function, after the properties object,in the Polymer call for registration.

ready: function() {
    document.querySelector("#anchor-for-" + this.modalId).setAttribute('data-dialog', this.modalId);
}

Very Cool! So now we have

  • A custom element registered as a Polymer element
  • Modal | Share | Fork icons added to the custom element

A Modal is attached to the info iron-icon,with the id “anchor-for-[Whatever is passed as modal-id]”. That is courtesy the ready method of our element.

So, so far, writing

<tool-bar
link2-share="http://www.myportfolio.com/project-neighbourhood-map"
link2-fork="https://github.com/me/project-neighbourhood-map"
modal-id="project-neighbourhood-map">
</tool-bar>

Produces this:

enter image description here

But when the user clicks on that info icon, something like This should happen

enter image description here

and our goal was to wrap this complete description of the project, within the <tool-bar> tag on the users page.

Remember Shadow DOM? We need to have a container in our custom element, that provides the shadow DOM for our Modal’s contents.The content itself, is wrapped inside a <content> tag inside the custom element’s shadowDOM.

For the container that hosts the Project’s description, we use the “paper-dialog” Polymer element. Paper-dialog, is assigned as id, whatever is passed as the modal-id in the declaration on the user’s page.

So, add this markup, after the ul in the tool-bar custom element’s DOM

<paper-dialog id="[[modalId]]" modal>
    <div class="text-right modal-close">
        <iron-icon icon="icons:power-settings-new" dialog-dismiss></iron-icon>
    </div>
    <h2 class="text-center text-capitalize">[[title]]</h2>
    <paper-dialog-scrollable>
        <div class="container-fluid">
            <div class="row flex-wrap info">
                <content></content>
            </div>
        </div>
    </paper-dialog-scrollable>
</paper-dialog>

Note: Paper-dialog-scrollable

We use Paper-dialog-scrollable, to wrap our Project’s description, so that, Any lengthy descriptions, do not overflow.

The last bit, is to add the onclick functionality for when the modal should open, on click of the info icon.

When a click happens, as is normal, an event is triggered, which we pass to our clickHandler function like so:

<iron-icon icon="icons:info" id="anchor-for-[[modalId]]" onclick="clickHandler(event)"></iron-icon>

So Once the clickHandler function gets the event passed to it,

  • It needs to gather, which element triggered the click,
  • It needs to gather, the data-dialog attribute of that element, to ascertain which modal to open(Remember each project has its own modal id?)
  • It then needs to call the open method, for exactly that modal

So, the function is like so:

Add this, before the element’s registration call.This is not a part of the element, but is scoped to within the element.

function clickHandler(e) {
    var button = e.target;
    while (!button.hasAttribute('data-dialog') && button !== document.body) {
        button = button.parentElement;
    }
 
    if (!button.hasAttribute('data-dialog')) {
        return;
    }
 
    var id = button.getAttribute('data-dialog');
    var dialog = document.getElementById(id);
    if (dialog) {
        dialog.open();
    }
}

So, with that, we have completed coding the custom element, <tool-bar>.