alpinejs / alpine

A rugged, minimal framework for composing JavaScript behavior in your markup.
https://alpinejs.dev
MIT License
28.29k stars 1.23k forks source link

bug in nested x-for #1019

Closed goldalworming closed 3 years ago

goldalworming commented 3 years ago

Hi, I found bug in nested x-for

this is data I want to show

[ { "id": 1, "kode": "1D ", "name": "Prepare for 5G", "show": 1, "program": [ { "id": 1, "kode_si": "1D", "name": "Lead To develop 5G Strategy and Roadmap from business point of view", "goal": "5G use-cases piloted", "keyprogress": "1,4,5,6" } ] }, { "id": 2, "kode": "5 ", "name": "Increase Group Technology Integration & Digitization", "show": 1, "program": [ { "id": 2, "kode_si": "5", "name": "Accelerate internal programs", "goal": "2021 DX programs executed (Target aligned in Dec. 2021)", "keyprogress": null }, { "id": 3, "kode_si": "5", "name": "Develop and formalize an integrated group cybersecurity strategy, roadmap & governance", "goal": "Group cybersecurity strategy, roadmap & governance approved by BOE", "keyprogress": null } ] } ]

when looping without child it work normally 1

but when I insert nested x-fro code it start show an extra row with error 2

and this is error shown 3

this is the code

      <tbody class="bg-white divide-y divide-gray-200">
        <template x-for="item,index in data" :key="item">
          <tr>
            <td class="px-6 py-4 whitespace-nowrap">
              <div class="flex items-center">
                <div class="">
                  <div class="text-sm font-medium text-gray-900" x-text="item.kode">
                  </div>
                  <div class="text-sm text-gray-700" x-text="item.name">
                  </div>
                </div>
              </div>
            </td>
            <td class="px-6 py-4 whitespace-nowrap">
              <!-- <template  x-for="item2 in item.program">
                <div class="text-sm text-gray-900 mb-2 border-b-2" x-text="item2.name"></div>
              </template> -->
            </td>
            <td class="px-6 py-4 whitespace-nowrap">
              <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
                Active
              </span>
            </td>
            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
              value
            </td>
            <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
              <a href="#" class="text-indigo-600 hover:text-indigo-900">value</a>
            </td>
            <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
              <a href="#" class="text-indigo-600 hover:text-indigo-900">value</a>
            </td>
            <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
              <a href="#" class="text-indigo-600 hover:text-indigo-900">value</a>
            </td>
            <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
              <a href="#" class="text-indigo-600 hover:text-indigo-900">value</a>
            </td>
          </tr>
        </template>
      </tbody>
goldalworming commented 3 years ago

how to solve this or any alternative code? the problem is I still have 2 level more nested inside this nested.

KevinBatdorf commented 3 years ago

I'm not seeing the error when I copy/paste your code to codepen. Can you put it into a demo in a broken state and share a URL?

https://codepen.io/KevinBatdorf/pen/6ef932653e6d67d1b0e57869a72dbe9d

goldalworming commented 3 years ago

just try this and it will show error

          <template  x-for="item2 in item.program">
            <div class="text-sm text-gray-900 mb-2 border-b-2" x-text="item2.name"></div>
            <div class="text-sm text-gray-900 mb-2 border-b-2" x-text="item2.goal"></div>
          </template>

image

KevinBatdorf commented 3 years ago

There's a warning at the bottom of your screenshot telling you how to fix that. You need to make sure your template tag only has a single child element.

<template  x-for="item2 in item.program">
  <div>
    <div class="text-sm text-gray-900 mb-2 border-b-2" x-text="item2.name"></div>
    <div class="text-sm text-gray-900 mb-2 border-b-2" x-text="item2.goal"></div>
  </div>
</template>
goldalworming commented 3 years ago

ah I'm sorry, thank's a lot for that but how to works with object that not defined yet like using ajax

  function tabledata() {
    return {
        data : []
        init(){
            this.data = [ { "si_id": 1, "kode": "1D ", "si_name": "Prepare for 5G", "show": 1, "program": [ { "id": 1, "kode_si": "1D", "name": "Lead To develop 5G Strategy and Roadmap from business point of view", "goal": "5G use-cases piloted", "keyprogress": [{"milestone_name":'1'}],"immediate": [{"milestone_name":'2'}] } ] }, { "si_id": 2, "kode": "5 ", "si_name": "Increase Group Technology Integration & Digitization", "show": 1, "program": [ { "id": 2, "kode_si": "5", "name": "Accelerate internal programs", "goal": "2021 DX programs executed (Target aligned in Dec. 2021)", "keyprogress": [{"milestone_name":'3'}],"immediate": [{"milestone_name":'4'}] }, { "id": 3, "kode_si": "5", "name": "Develop and formalize an integrated group cybersecurity strategy, roadmap & governance", "goal": "Group cybersecurity strategy, roadmap & governance approved by BOE", "keyprogress": [{"milestone_name":'5'}],"immediate": [{"milestone_name":'6'}] } ] } ]    
        }
    }
  }

looping will break before data complete at init

KevinBatdorf commented 3 years ago

Can you set up a codepen or another demo where it's broken? Otherwise I will have to set it up myself, and last time I did that the code worked fine.

goldalworming commented 3 years ago

oh I found my mistake, some properties not defined when ajax returned

<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <link rel='stylesheet' href='https://unpkg.com/tailwindcss/dist/tailwind.min.css'>
  <style>
  [x-cloak] { display: none; }
  </style>
</head>

<body translate="no" >
  <div class="min-h-screen p-16 bg-gray-100">
    <div x-data="tabledata()" x-init="init()">
        <tbody class="bg-white divide-y divide-gray-200">
            <template x-for="item,index in data" :key="item">
              <tr>
                <td class="px-6 py-4 whitespace-nowrap w-1/4">
                  <div class="flex items-center">
                    <div class="">
                      <div class="text-sm font-medium text-gray-900" x-text="item.si_id">
                      </div>
                      <div class="text-sm text-gray-700" x-text="item.si_name">
                      </div>
                    </div>
                  </div>
                </td>
                <td class="px-6 py-4 whitespace-nowrap">
                  <template  x-for="item2 in item.program">
                    <div class="flex">
                      <div class="text-sm text-gray-900 mb-2 border-b-2 w-1/4" x-text="item2.name"></div>
                      <div class="text-sm text-gray-900 mb-2 border-b-2 w-1/4" >
                        <template  x-for="item3 in item2.keyprogress">
                          <div class="w-full" x-text="item3.milestone_name"></div>
                        </template>
                      </div>
                      <div class="text-sm text-gray-900 mb-2 border-b-2 w-1/4" >
                        <template  x-for="item3 in item2.immediate">
                          <div class="w-full" x-text="item3.milestone_name"></div>
                        </template>
                      </div>
                      <div class="text-sm text-gray-900 mb-2 border-b-2 w-1/4" x-text="item2.goal"></div>
                    </div>
                  </template>
                </td>
                <td class="px-6 py-4 whitespace-nowrap">
                  <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
                    Active
                  </span>
                </td>
              </tr>
            </template>
          </tbody>
    </div>
  </div>
  <script src='https://cdn.jsdelivr.net/gh/kevinbatdorf/alpine-inline-devtools/dist/Dracula.js'></script>
  <script src='https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js'></script>
      <script id="rendered-js" >
        function tabledata() {
          return {
            data : [],
            init(){
              this.loaddata()
            },
            async loaddata (){
              function sleep(ms) {
                return new Promise(resolve => setTimeout(resolve, ms));
              }
              await sleep(1000);
              //error
              dataerror = [{"si_id":1,"kode":"1D ","si_name":"Prepare for 5G","show":1},{"si_id":2,"kode":"5 ","si_name":"Increase Group Technology Integration & Digitization","show":1}]

              datafine = [{"si_id":1,"kode":"1D ","si_name":"Prepare for 5G","show":1,"program":[]},{"si_id":2,"kode":"5 ","si_name":"Increase Group Technology Integration & Digitization","show":1,"program":[]}]

              //works fine
              this.data = datafine
            }
          }
        }
    </script>
</body>

</html>

thank you very very much