Search code examples
javascriptnunjucks

Loop through nested object properties nunjucks


I have a nested object like this

contract: {
        packages: [
            {
                servicePoint: {
                    productType: {
                        name: 'Name1'
                    }
                },
                packages: [
                    {
                        servicePoint: {
                            productType: {
                                name: 'Name1'
                            }
                        }

                    },
                    {
                        servicePoint: {
                            productType: {
                                name: 'Name2'
                            }
                        }

                    }

                ]
            }
        ]
    }

I would like to loop through nested object and find all productType.name values if it's exists. and create elements

<button type="button">{{ servicePoint.productType.name }}</button>

I could do something like this

{% for servicePoint in contract.packages[0].packages[0].servicePoints %}

But it will find properties only under second level of object.


I have found some solution

{% if contract.packages.length > 0 %}
        {% for item in contract.packages %}
            {% if item.servicePoints.length > 0 %}
                {% set names =     (names.push(item.servicePoints[0].productType.name), names) %}
            {% endif %}
            {% if item.packages.length > 0 %}
                {% for value in item.packages %}
                        {% set names = (names.push(value.servicePoints[0].productType.name), names) %}
                {% endfor %}
            {% endif %}
        {% endfor %}
    {% endif %}

But I got new problem. If it find the same productType.name, it create two buttons with the same value.

How could I uniq productType.name ?


Solution

  • You can check that name already exists in names before push.

    P.S. I'm not sure that passed to template "unbalanced" structure is good idea. Because set arr = (arr.push(item), arr) is a trick.

    {% if contract.packages.length > 0 %} // You can don't check length. It's not a necessary.
    
        {% for item in contract.packages %}
            {% if item.servicePoints.length > 0 %}
                {% set names = (names.push(item.servicePoints[0].productType.name), names) %}
            {% endif %}
    
            {% if item.packages.length > 0 %}
                {% for value in item.packages %}
                    {% if names.indexOf(value.servicePoints[0].productType.name) == -1 %} // <=
                        {% set names = (names.push(value.servicePoints[0].productType.name), names) %}
                    {% endif %} // <=
                {% endfor %}
            {% endif %}
    
        {% endfor %}
    
    {% endif %}