Tuesday, June 21, 2016

Polymer 1.0: dom-repeat tutorial part 2

cat-appender is the name of the element we are creating

Dom-repeat is one of the most useful helper elements in Polymer, in this post series we’ll go through a working example adding, removing and retrieving data, step by step explaining what is happening and linking to the appropriate documentation page for more in-depth details.


This post is part 2 of a 2-part series. Find part 1 here.
This post will discuss how to add, remove and retrieve elements.

Here's a demo of what the final result will look like.



Let users add their kitties


In your element's template (cat-appender.html in the demo), add this div right before the <ul>, a text input for the name and another one for the age, and a button to take these values and add it to the cat list.
<div>
  <input type="text" id="kittyName" placeholder="Name">
  <input type="text" id="kittyAge" placeholder="Age">
  <button on-click="_addKitty">Add</button>
</div>
Note the “on-click” annotation here, this is used by Polymer as a shortcut to assign an event listener to the element in the local dom rather than giving it an id and registering the event listener in the element prototype. Docs

Now, let’s define the “_addKitty” function.
In the element’s prototype definition inside your script, take a comma and add this, right after the properties object.
_addKitty: function() {
    var kittyName = this.$$('#kittyName').value;
    var kittyAge  = this.$$('#kittyAge').value;

    this.push("kitties", {name: kittyName, age: kittyAge});
}

  • The first two lines get the values that are entered in the inputs, this is Polymer’s special syntax for the normal “querySelector” method. Here are all options for element selection.
  • Last line is pushing an object into the kitties array, note the “this.push()” method, this is one of Polymer’s Array mutation methods, this syntax makes all listeners (observers, bound elements) to this array be notified with the change and they adapt to reflect it. If it was “this.kitties.push” the list won't update, unless you notify the listeners manually through notifySplices or notifyPath, but I haven’t really been in a situation that I had to use them.


Removing cats


We are still in the element's template (cat-appender.html in the demo).

Add a button right after the opening tag of the <li> inside the dom-repeat so it looks like this.

<li>
  <button on-click="_removeKitty">Remove</button>
  [[kitty.name]] : [[kitty.age]]
</li>

so every cat has its remove button to the left of it.


Now define the “_removeKitty” function.

Add a comma after the previous “_addKitty” function and define the new function like this.

_removeKitty: function(e) {
    var index = this.kitties.indexOf(e.model.kitty);
    this.splice('kitties', index, 1);
}

  • Every item inside the dom-repeat carries a “model” object which it hands to its event handler (More details), this model carries the properties of its “row”, what concerns us here is the “item” itself.
  • Note that the item is referenced with its alias (if any is defined), so refer to the item with model.item by default, and model.alias when you specify as=”alias” in your dom-repeat.
  • Last line is again using an array mutation method to remove the item from the array.


Getting the element’s data from the outside world

Now we will define a function that users of this element will use to retrieve the inserted data.

In the element template, add this function to the prototype.
getData: function() {
    return this.kitties;
}
This function just returns the kitties (data) array to the caller.

In the demo page (index.html in the demo), add a div and a button that will print out the data inside the div when clicked.

<div>
  <button onclick="displayData()">Get data</button>
  <div id="dataDiv"></div>
</div>

And add the “displayData” function.
<script>
  var displayData = function() {
    var catAppender = document.querySelector("cat-appender");
    document.querySelector("#dataDiv").innerHTML = JSON.stringify(catAppender.getData());
  };
</script>


That’s it, now you have a repeating template which supports add, delete and retrieve operations on the data.

Friday, June 17, 2016

Polymer 1.0: dom-repeat tutorial part 1

cat-appender is the name of the element we are creating

Dom-repeat is one of the most useful helper elements in Polymer, in this post series we’ll go through a working example adding, removing and retrieving data, step by step explaining what is happening and linking to the appropriate documentation page for more in-depth details.


This post is part 1 of a 2-part series, it will discuss how to setup the element and basic dom-repeat.


First off, I’m assuming that you know what polymer is and that you have Created an element project.


The element we are going to work on is repeating unordered list items, it is called “cat-appender” (because I like cats, but feel free to name it whatever you like :3).

Here's a demo of what the final result will look like, I’ve removed all the clutter to focus on the element itself.


Enough talking, let’s dive in:

Setting up the element

We will start by setting up the element, that is giving it the required properties and template.


Here’s what the element prototype looks like (at the end of cat-appender.html in the demo) :



<script>
  Polymer({
    is: 'cat-appender',
    properties:{
      kitties: Array
    }
  });
</script>

We have a sole property defined in the properties object, that’s the array that will go inside the “dom-repeat” in a moment, it’s an array of objects as you may have guessed.

Here’s what the template looks like (cat-appender.html in the demo still):
Inside your <dom-module> and <template> elements
<ul>
  <template is="dom-repeat" items="[[kitties]]" as="kitty">
    <li>
      [[kitty.name]] : [[kitty.age]]
    </li>
  </template>
</ul>

I assume that you came to this post because you’ve read about basic dom-repeat somewhere, so I’m going with a quick explanation about what’s going on here:

  • We are telling Polymer that we want to repeat the enclosed markup with the <template is="dom-repeat">.
  • We provide the data we want to iterate on as the “items” property, here, it is the “kitties” property that we defined earlier for the element prototype, it takes its value from the parent (the “host” element when used in a page).
  • “as” property gives an alias to the default “item” that is used to reference the current item that the dom-repeat is iterating over at the moment, this property is commonly used in nested dom-repeats to reference parent template, but I thought it’s worth mentioning.
  • Inside we are rendering an <li> for every item (object) in the array, notice that we’ve used the alias “kitty” instead of the default “item” that we would’ve used otherwise.



Notes on data binding annotations

Choosing an annotation for data binding may seem confusing at first, make sure that you read through the documentation and get your head around it.

As a simple rule: one-way data binding ( [[ ]] ) will be suitable when the goal is to show (read) or use the data without modifications, like when we used it to iterate over the kitties array in the dom-repeat.

While automatic binding ( {{ }} ) is most useful when binding to data that will change, like an input value or an element property (not attribute, see attribute binding if you want to investigate), or when binding to array items (As they are always two-way).




Now, on the file that you’ll show your element in (index.html in the demo):


<link rel="import" href="cat-appender.html">

<h3>Cat list</h3>
<cat-appender 
kitties='[{"name": "Simba", "age": 29}, {"name": "Mufasa", "age": 35}, {"name": "Sylvester", "age":71} ]' >
</cat-appender>

That code imports the element that we just created, and shows it on the page (if you have created an element project, you already have it setup in your demo directory), we then give it an array of objects (cats with names and ages, in this case) as a property.



Note:

  • Single quotes are being used for the property itself, that’s because this array is being deserialized into a JSON string, which must have double quotes.
  • Also the property names for the objects are enclosed in double quotes, it will not deserialize properly if you remove the quotes (because it’s a JSON string, not a Javascript object). Further reading
We now have a template that is repeated on an array, nothing very interesting so far.
In the next part we will let the user add a cat, remove a cat and retrieve the cats in the list through our “API”, stay tuned, it’s coming very soon..


Update: part 2 is here