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
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.
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.
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
Also, we have bound the attributes the user writes, to the respective properties.
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 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:
But when the user clicks on that info icon, something like This should happen
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>
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,
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>
.