Lakshay Khandelwal
Lakshay Khandelwal

Reputation: 81

Why the child table(toggle-table) is repeating whenever clicked on the row of the parent table?

I have tried to make a table which contains the GDP of country states. When anyone clicks on the state row the child table(district GDP table) appears. It is working correctly but the child table in repeating. I have made a toggle function to control the hide/show of the child table. Can anyone find out why the child table is repeating? Solution for this will be appreciated.

Run the Snippet to understand the problem properly.

  var app = new Vue({
  el: "#app",
  data(){
    return {
    opened:[],
    stateGDP: [
        { State: "Rajasthan", "1999-00": "2547", "2000-01": "3679",Id:"23" },
        { State: "Orissa", "1999-00": "38714", "2000-01": "38814",Id:"24" }
      ],
      DistrictGDP: [
        {
          State: "Rajasthan",
          District: "Jaipur",
          "1999-00": "2547",
          "2000-01": "3679",
          Id:"23"
        },
        {
          State: "Rajasthan",
          District: "Jodhpur",
          "1999-00": "2557",
          "2000-01": "3639",
          Id:"23"
        },
        {
          State: "Orissa",
          District: "Bhubaneswar",
          "1999-00": "1983",
          "2000-01": "2068",
          Id:"24"
        },
        {
          State: "Orissa",
          District: "Puri",
          "1999-00": "1923",
          "2000-01": "2008",
          Id:"24"
        }
      ]
      }
    },
  methods:{
    toggle:function(Id) {
    const index = this.opened.indexOf(Id);
    if (index > -1) {
      this.opened.splice(index, 1)
    } else {
      this.opened.push(Id)
    }
 }
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
        <div class="table">
          <table class="table-fill">
            <thead>
            <tr>
    <th class="text-center">State/UT</th>
    <th class="text-center">1999-00</th>
    <th class="text-center">2000-01</th>
</tr>
</thead>
  <template v-for="row in stateGDP">
    <tr @click="toggle(row.Id)" :class="{ opened: opened.includes(row.Id) }">
      <td>{{ row.State }}</td>
      <td>{{ row['1999-00'] }}</td>
      <td>{{ row['2000-01'] }}</td>
    </tr>
    <template v-for="(xy, indexStop) in DistrictGDP" v-if="opened.includes(row.Id) && row.Id==xy.Id">
    <thead>
    <tr>
<th class="text-center">District</th>
<th class="text-center">1999-00</th>
<th class="text-center">2000-01</th>
</tr>
</thead>
    <template v-for="xy in DistrictGDP" v-if="opened.includes(row.Id) && row.Id==xy.Id">
   <tr>
     <td colspan="1">{{xy.District}}</td>
     <td colspan="1">{{xy['1999-00']}}</td>
     <td colspan="1">{{xy['2000-01']}}</td>
   </tr></template>
   </template>
</template>
</table>
</div>
</div>

Upvotes: 0

Views: 63

Answers (1)

Andres Foronda
Andres Foronda

Reputation: 1419

  var app = new Vue({
  el: "#app",
  data(){
    return {
    opened:[],
    stateGDP: [
        { State: "Rajasthan", "1999-00": "2547", "2000-01": "3679",Id:"23" },
        { State: "Orissa", "1999-00": "38714", "2000-01": "38814",Id:"24" }
      ],
      DistrictGDP: [
        {
          State: "Rajasthan",
          District: "Jaipur",
          "1999-00": "2547",
          "2000-01": "3679",
          Id:"23"
        },
        {
          State: "Rajasthan",
          District: "Jodhpur",
          "1999-00": "2557",
          "2000-01": "3639",
          Id:"23"
        },
        {
          State: "Orissa",
          District: "Bhubaneswar",
          "1999-00": "1983",
          "2000-01": "2068",
          Id:"24"
        },
        {
          State: "Orissa",
          District: "Puri",
          "1999-00": "1923",
          "2000-01": "2008",
          Id:"24"
        }
      ]
      }
    },
  methods:{
    toggle:function(Id) {
    const index = this.opened.indexOf(Id);
    if (index > -1) {
      this.opened.splice(index, 1)
    } else {
      this.opened.push(Id)
    }

 },
    getRows(id) {
      return this.DistrictGDP.filter(district => district.Id === id);
    }
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js">. 
</script>
<div id="app">
  <div class="table">
    <table class="table-fill">
      <thead>
        <tr>
          <th class="text-center">State/UT</th>
          <th class="text-center">1999-00</th>
          <th class="text-center">2000-01</th>
        </tr>
      </thead>
      <template v-for="row in stateGDP" :class="{ opened: opened.includes(row.Id) }">
        <tr @click="toggle(row.Id)" style="background-color: #D3D3D3">
          <td>{{ row.State }}</td>
          <td>{{ row["1999-00"] }}</td>
          <td>{{ row["2000-01"] }}</td>
        </tr>
        <template
          v-if="opened.includes(row.Id)"
        >
          <thead>
            <tr>
              <th class="text-center">District</th>
              <th class="text-center">1999-00</th>
              <th class="text-center">2000-01</th>
            </tr>
          </thead>
        <tr v-for="(district, index) in getRows(row.Id)">
          <td colspan="1">{{district.District}}</td>
          <td colspan="1">{{district['1999-00']}}</td>
          <td colspan="1">{{district['2000-01']}}</td>
        </tr>
        </template>
      </template>
    </table>
  </div>
</div>

   

Now the explanation, in order to get the rows that you want to show on click, you are doing a v-for loop, and recreating the header and the whole nested table the same amount of times that the DistrictGDP exist with the same Id that stateGDP (two times in this case).

I removed that v-for (the second one in the whole code) and for render the nested table rows I added a method, getRows, this method filters the required rows based in the row.Id, that way the table doesn't need to compare if the id in the DistrictGDP is the same in the stateGDP.

Please, if I'm not being clear, let me know.

Upvotes: 3

Related Questions