Модальная проблема Bootstrap Vue + Nuxt JS внутри v-for

Я создаю приложение, подобное Trello, в котором у меня есть доски, списки и карточки, а данные сохраняются в базе данных в реальном времени в Firebase для тестирования.

Я использую модальные окна Bootstrap Vue для переключения видимость. Однако у меня проблема ...

Для начала у меня есть <b-modal> в карточке Bootstrap, у которой есть v-for, которая извлекает список карточек из списка списков, находящихся на досках. И я хочу показать данные карты после щелчка в модальном окне, и если я нажму другую карту, она будет использовать тот же элемент <b-modal>, но отображать другие данные.

С моей реализацией я, кажется, вызываю Maximum call stack size exceeded и буквально 5000+ ошибок вызывает сбой браузера, это выглядит не очень хорошо: D

Я провел некоторую отладку и попытался использовать методы с return false;, чтобы узнать, что на самом деле происходит, и модальное окно отображается, но при отклонении модального окна оно снова всплывает, вызывая таким образом ошибку.

Ниже я прилагаю соответствующий код и JS:

Разметка HTML

<b-col md="4" v-for="(list, index) in board.lists" :key="list.id">
              <b-card bg-variant="light" header-tag="header" footer-tag="footer">
                <div slot="header" class="mb-0">
                  <b-row>
                    <b-col md="8">
                      <h4 class="mb-0"><b-form-input size="sm" class="mr-sm-2 input-is-editable" type="text" placeholder="Enter list name..." v-model="list.name" /></h4>
                    </b-col>
                  </b-row>
                </div>
                <b-card class="mb-3" v-for="(card, index) in list.cards" :key="card.id" v-b-modal.prevent="modalId(index)">{{ card.name }}
                  <b-modal :id="'modal' + index" hide-footer title="Using Component Methods">
                    <div class="d-block text-center">
                      <h3>{{ card.name }}</h3>
                    </div>
                    <b-button class="mt-3" variant="outline-danger" block>Close Me</b-button>
                  </b-modal>
                </b-card>
                <div slot="footer" class="mb-0">
                  <b-row>
                    <b-col>
                      <b-nav-form>
                        <b-form-input size="sm" class="mr-sm-2" type="text" placeholder="Enter card name..." v-model="cardname" />
                        <b-button size="sm" variant="success" class="my-2 my-sm-0" type="button" @click="addCard(index)" :disabled="!cardname">Add card</b-button>
                      </b-nav-form>
                    </b-col>
                  </b-row>
                </div>
              </b-card>
            </b-col>

JS

export default {
  data () {
    return {
      id: this.$route.params.id,
      board: [],
      cards: [],
      lists: [],
      listname: '',
      cardname: '',
      editedFields: {}
    }
  },
  created() {
    this.$http.get('myfirebaseurl/boards/' + this.id + '.json').then(response => {
      this.board = response.body
    }, response => {
      // handle error for fetching property data.
    });
  },
  methods: {
    modalId(index) {
      return 'modal' + index;
    }
  }
}

JS - это еще не все, но я прилагаю только то, что относится к разметке выше.

Есть предложения, что я делаю не так и как исправить?

введите здесь описание изображения

огромное спасибо!


person Ryan H    schedule 23.02.2019    source источник
comment
Вероятно, у вас не должно быть модального окна в v-for. Если вы поместите его в верхнюю часть вашего html, у вас может быть событие @click внутри v-for, которое передает необходимые данные в модальное окно и открывает его.   -  person Andrew1325    schedule 24.02.2019


Ответы (1)


Я бы скорее согласился с @ Andrew1325, который указал, что создание одного экземпляра модального диалога и передача выбранных данных может быть лучшим вариантом, например

 <div>
    <div v-for="(item) in items" :key="item.id">
      <b-card
        :title="item.title"
        :img-src="item.imageUrl"
        img-alt="Image"
        img-top
        tag="article"
        style="max-width: 20rem;"
        class="mb-2"
      >
        <b-card-text>{{item.text}}</b-card-text>

        <b-button variant="primary" @click="showModal(item)">Show details</b-button>
      </b-card>
    </div>
    <b-modal id="modal1" :title="selectedItem.title">
      <img style="max-width: 20rem;" :src="selectedItem.imageUrl"/>
      <p class="my-4">{{selectedItem.text}}</p>
    </b-modal>
</div>



export default {
  data() {
    return {
      selectedItem: {},
      items: [
        {
          id: 1,
          title: "First",
          imageUrl : "https://picsum.photos/600/300/?image=23",
          text: "Some quick example text to build on the card title and make up the bulk of the card's content"
        },
        {
          id: 2,
          imageUrl : "https://picsum.photos/600/300/?image=24",
          title: "Second",
          text: "Some quick example text to build on the card title and make up the bulk of the card's content"
        },
        {
          id: 3,
          imageUrl : "https://picsum.photos/600/300/?image=25",
          title: "Third",
          text: "Some quick example text to build on the card title and make up the bulk of the card's content"
        }
      ]
    };
  },
  methods: {
    showModal(item){
      this.selectedItem = item;
      this.$root.$emit("bv::show::modal", "modal1");
    }
  }
};

Демо

person Vadim Gremyachev    schedule 24.02.2019