アリ・ナディム
アリ・ナディム

Reputation: 610

How to loop nested data in alpine? dynamic

I have here sample families data which has nested children. My problem is I don't know how many x-for should I write since the nested is dynamic (from Database). Would appreciate any answer.

Here's my sample data in the snippet below:

$families = [
    {
        id: 1,
        name: 'Lupe',
        children: [
            {
                id: 3,
                name: 'Bertha',
                children: [
                    {
                        id: 5,
                        name: 'Hollywood',
                        children: [
                            {
                                id: 6,
                                root: 5,
                                children: [],
                            },
                        ]
                    },
                ],
            },
            {
                id: 9,
                name: 'Pinnick',
                children: [
                    {
                        id: 10,
                        name: 'Andy',
                        children: []
                    },
                ]
            },
        ]
    },
    {
        id: 2,
        name: 'Smitty',
        child: [
            {
                id: 4,
                name: 'Vito',
                children: []
            },
        ],
    }
];


Here is the expected output enter image description here


Draft implementation:

<tbody>
    <template x-for="(family, familyKey) in families">
        <template x-for="(parent, parentIndex) in family">
            <tr :class="rowClass(scenarioKey, itemIndex)">
                <h1 x-text="parent.name"></h1>
            </tr>
        </template>
    </template>
</tbody>

Upvotes: 0

Views: 771

Answers (1)

Dauros
Dauros

Reputation: 10577

You need a recursive rendering function using x-html directive so make sure that the content is safe, otherwise you can put XSS vulnerabilities in your code. Based on this we can write a recursive list generation function that follows the family graph and renders each level:

<div x-data="familyTree">
  <ul>
    <template x-for="(level, i) in families">
      <li x-html="renderLevel(level, i)"></li>
    </template>
  </ul>
</div>


<script>
document.addEventListener('alpine:init', () => {
  Alpine.data('familyTree', () => ({
    families: [
      {
        id: 1,
        name: 'Lupe',
        children: [
          {
            id: 3,
            name: 'Bertha',
            children: [
              {
                id: 5,
                name: 'Hollywood',
              },
            ],
          },
          {
            id: 9,
            name: 'Pinnick',
            children: [
              {
                id: 10,
                name: 'Andy',
                children: []
              },
            ]
          },
        ]
      },
      {
        id: 2,
        name: 'Smitty',
        children: [
          {
            id: 4,
            name: 'Vito',
            children: []
          },
        ],
      }
    ],

    renderLevel(obj, i) {
      let has_children = obj.children && obj.children.length
      let html = `<span style="padding-left: 10px;"
                     x-html="'${has_children ? '> ' : '- '}' + level.name"></span>`;

      if (obj.children) {
        html += `<ul style="padding-left: 10px; padding-bottom: 10px;">
                  <template x-for='(level,i) in level.children'>
                      <li x-html="renderLevel(level,i)"></li>
                  </template>
                </ul>`;
      }

      return html;
    },
  }))
})
</script>

Output:

> Lupe    
    > Bertha
        - Hollywood
    > Pinnick
        - Andy

> Smitty    
    - Vito

Upvotes: 1

Related Questions