Search code examples
vuejs2modal-dialogvue-componentv-for

Why the index of a v-for used as a method parameter in another component doesn't equal to the initial index value?


My problem is the following one: I have a list of bank accounts, they are looped in a v-for. For each bank account, I have a button to be able to delete it. When a user delete a bank account, I want to display a confirmation modal with a confirm method. I have to pass the index of the v-for to the method to know which element I have to delete from the original array. When I passed that index, it doesn't match to the index of the current element. Here is a visual support:

<div v-for="(bankAccount, index) in bankAccounts" :key="bankAccount.id">
  <ModalConfirm @close="showModal = false" @confirmDelete="deleteBA(index)" v-if="showModal" />

  <div>
    <section>
      <p class="color--lg light">{{ bankAccount.name }}</p>
    </section>

    <section>
      <button @click="showModal = true">
        Delete bank account
      </button>
    </section>
  </div>
</div>

So here, the index value in the method deleteBA is not the same than the original index of the v-for. I can't understand why !

I created a live example:

https://codesandbox.io/s/6jo79vr1lk

Thanks for any help !


Solution

  • The issues is in the following code:

    <template>
      <div class="hello card-container">
        <ul v-for="(element, index) in elements" :key="index">
          <li class="card">
            <div>{{ index }}</div>
            <div>
              <button @click="showModal = true;">Delete bank account {{element}}</button>
            </div>
            <ModalConfirm
              @close="showModal = false;"
              @confirmDelete="deleteBA(index);"
              v-if="showModal"
            />
          </li>
        </ul>
      </div>
    </template>
    

    you have one modal for each account , but use a single boolean value to toggle all. @click="showModal = true;"

    While there are ways to handle that by adding a modal boolean for each item, it's unnecessary to have a modal for each item, and better to reuse the same modal.

    you can use a modal index instead of a boolean, so @click="showModal = index"

    <template>
      <div class="hello card-container">
        <ul v-for="(element, index) in elements" :key="index">
          <li class="card">
            <div>{{ index }}</div>
            <div>
              <button @click="showModal = index;">Delete bank account {{element}}</button>
            </div>
          </li>
        </ul>
        <ModalConfirm
          @close="showModal = -1"
          @confirmDelete="deleteBA(showModal);"
          v-if="showModal >= 0"
        />
      </div>
    </template>
    

    Edit Vue Template