Search code examples
intjinja2nunjucks

Nunjucks within loop, convert attribute to int and sort by int?


I have an object:

[
  {
   "block": "1",
   ...
   "block": "2",
   ...
   "block": "11"

and I want to sort on block as an integer, not as a string (which sorts 1, 11, 2):

<!-- sorts as string -->
{% for standard in standards | sort(false, true, 'standard.block') %}

I tried to convert standard.block to an int with no effect

{% for standard in standards | sort(false, true, '{{ standard.block | int }}') %}

Solution

  • As you can see: nunjucks sorts elements with string comparator (default js behaviour). So you should convert block-property to Number before sorting or use a custom filter e.g. sortBy

    const nunjucks  = require('nunjucks');
    const env = nunjucks.configure();
    env.addFilter('sortBy', function (arr, prop) {
        const isNum = val => val == +val;
        const sorter = (a, b) => isNum(a[prop]) && isNum(b[prop]) ? +a[prop] - b[prop] : a[prop] < b[prop];
        arr.sort(sorter);
        return arr; 
    });
    
    const html = env.renderString(
        `{% for item in items | sortBy('block') %} 
            {{item.block}} {{ item.color}} 
        {% endfor %}`, 
        { 
            items: [
                { block: "1", color: 'Blue' },
                { block: "7", color: 'Green' },
                { block: "3", color: 'Yellow' }
            ]
        }
    );
    
    console.log(html);