Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort an iron-list in Polymer 1.0?

I am looking to sort data in an iron-list (and also sort items as they are added into the data array).

Sample (unsorted) json data:

[
  {"name": "Zebra"},
  {"name": "Alligator"},
  {"name": "Lion"}
]

I have tried using the indexAs property to sort an iron-list as follows but the API isn't clear how to use it:

<iron-ajax url="./data.json" last-response="{{data}}" auto></iron-ajax>
<iron-list items="[[data]]" as="item" index-as="name" class="fit">
  <template>
    <div>
      Name: <span>[[item.name]]</span>
    </div>
  </template>
</iron-list>
like image 680
David Douglas Avatar asked Mar 15 '23 02:03

David Douglas


2 Answers

I'm not exactly sure if there's more native Polymer way to do this, but it's not too complex to build the sorting logic yourself.

The idea is to listen to the response event, sort the data from the service and then bind the items of the iron-list to the sortedData.

You will need to add on-response="_onResponseReceived" to your iron-ajax. And then it's just a matter of sorting the returned data.

_onResponseReceived: function () {
    this.sortedData = this.data.sort(this._compare);
},

_compare: function (a, b) {
    if (a.name < b.name)
        return -1;
    if (a.name > b.name)
        return 1;
    return 0;
}

Of course the iron-list now needs to be updated to

<iron-list items="[[sortedData]]" ...>
like image 193
Justin XL Avatar answered Mar 26 '23 22:03

Justin XL


With Polymer 1.2.4 if you want to sort an iron-list in a dynamic fashion you can also take advantage of this.querySelector('iron-list').notifyResize(); to force a refresh after you update the sortedItems array in your observer. This is a hack but if you don't do this unfortunately polymer doesn't refresh the list for you. Let's sort by id or name our items:

<template>
    <paper-icon-button icon="expand-more" on-tap="_sortItems" sort-option="id"></paper-icon-button>
    <paper-icon-button icon="expand-more" on-tap="_sortItems" sort-option="name"></paper-icon-button>

    <iron-list items="[[sortedItems]]">
        <template>
            <p>[[item.name]]<p>
        </template>
    </iron-list>
</template>
...
properties: {
    ...
    sortByTerm: {
        type: String,
        value: 'id'
    },
    sortByOrder: {
        type: Number,
        value: -1 // Descending order
    },
},
observers: [
    'sortingObserver(items.*, sortByTerm, sortByOrder)'
],
sortingObserver: function(items, sortByTerm, sortByOrder) {
    var sortedItems = [],
    validSortingOptions = ['id', 'name'];

    if (validSortingOptions.indexOf(sortByTerm) != -1) {
        sortedItems = items.base.sort(this._computeSort(sortByTerm, sortByOrder));
    } else {
        sortedItems = items.base;
    }

    this.set('sortedItems', sortedItems);
    this.querySelector('iron-list').notifyResize();
},
_computeSort: function(property, order) {
    return function(a, b) {
        if (a[property] === b[property]) {
            return 0;
        }
        return (order * (a[property] > b[property] ? 1 : -1));
    };
},
_sortItems: function(e) {
    var sortByTerm = e.currentTarget.getAttribute('sort-option');
    this.set('sortByTerm', sortByTerm);
},
...
like image 30
Marios Fakiolas Avatar answered Mar 26 '23 21:03

Marios Fakiolas