VueJs // V-for с v-modal // Проблема обновления данных после нажатия кнопки

ОБНОВЛЕНО !!! Добавлен полный код компонента: входные данные отображаются с помощью цикла v-for. Список входных данных зависит от ответа API. Мне нужны кнопки «плюс» и «минус», чтобы изменить значение ввода. Я почти нахожу решение, но значение изменяется только при изменении входных данных родного брата, но не при нажатии кнопки. Вот мой код ...

 <template>
  <div class="allPlaces" id="allPlaces">
    <div class="wiget__row wiget__row--top" id="topRow">
      <div class="wiget__details wiget__details--allPlaces">
        <div class="wiget__logo">
          <img class="wiget__img wiget__img--logo" width="28" height="30" src="../../img/kassy_logo_img.png" alt="">
          <img class="wiget__img wiget__img--logoTXT" width="59" height="28" src="../../img/kassy_logo_text.png" alt="">
        </div>
        <div class="wiget__eventDetails">
          <p class="wiget__eventName">{{this.show[0].title}}</p>
          <div class="wiget__place">
            <span class="wiget__venue">{{this.building[0].title}}, </span>
            <span class="wiget__venueHall">{{this.hall[0].title}}</span>
          </div>
          <div class="wiget__dateOfEvent">
            <span class="wiget__time">{{this.getTime(this.event[0].date)}}</span>
            <span class="wiget__date">{{this.getDate(this.event[0].date)}}</span>
          </div>
        </div>
      </div>
    </div>

    <div class="allPlaces__wrapper">
      <h1 class="allPlaces__title">Оформление заказа</h1>
      <p class="allPlaces__description">Для оформления заказа выберите нужное количество мест</p>
      <div class="allPlaces__content">
        <div class="allPlaces__entrance" v-for="(entrance, index) in places.entrance" :key="entrance.id">
          <div class="allPlaces__infoBlock">
            <div>
              <div class="allPlaces__available">
                <span class="allPlaces__label allPlaces__label--places">Доступно мест:</span>
                <span class="allPlaces__data">&nbsp{{entrance.vacant_places}}</span>
              </div>
              <div class="allPlaces__title allPlaces__title--entrance">{{getEntranceName(entrance)}}</div>
            </div>
            <div class="allPlaces__price">
              <span class="allPlaces__label">Цена: </span>
              <span class="allPlaces__data">{{entrance.price}}</span>
            </div>
          </div>

          <div class="allPlaces__orderBlock">
            <div class="allPlaces__inputBlock">
              <input class="allPlaces__input" type="number" name="amount" v-bind:id="tickets"
                    v-model="tickets[index]" @blur="showLabel($event, index)">
              <label class="allPlaces__label allPlaces__label--input"
                     @click="hideLabel($event, index)">Количество мест

              </label>
            </div>

            <div class="allPlaces__btnBlock">
              <button class="allPlaces__btn allPlaces__btn--minus" type="button" name="button"
                      @click="removeTicket(index)"></button>
              <button class="allPlaces__btn allPlaces__btn--plus" type="button" name="button"
                      @click="addTicket(index)">
              </button>
            </div>
            <button class="allPlaces__btn allPlaces__btn--confirm" type="button" name="button"
                  @click="addEntrancePlaceToCart(entrance, index)">
                  <img class="allPlaces__img allPlaces__img--cart" src="../../img/cartWhite.png" alt="Корзина">
                  <span class="allPlaces__text allPlaces__text--cart">В корзину</span>
            </button>
          </div>
        </div>
      </div>
    </div>

    <div class="wiget__row wiget__row--bottom" id="bottomRow">
       <div class="wiget__row">
         <div class="wiget__amountBlock">
           <span class="wiget__tickets">
             <span>Билеты:</span>
             <span class="wiget__amount wiget__amount--tickets">{{this.ticketsInCart.count}}</span>
             <span>шт.</span>
           </span>
           <div class="wiget__money">
             <span class="wiget__money wiget__money--label">Итого:</span>
             <p>
               <span class="wiget__amount wiget__amount--money">{{this.ticketsInCart.total}}&nbsp</span>
               <span class="wiget__amount wiget__amount--money">руб.</span>
             </p>
           </div>
         </div>
         <div class="wiget__btnBlock">
           <button class="wiget__btn wiget__btn--goToHall" type="button" name="button"
                   @click="goToHall()">
                 Выбрать на схеме
           </button>
           <button class="wiget__btn wiget__btn--confirm" type="button" name="button"
           @click="goToCartPage($event)">Оформить заказ</button>
         </div>
       </div>
       <div class="wiget__row wiget__row--service">
         <span class="wiget__service">Сервис предоставлен:</span>
         <a href="https://www.kassy.ru" class="wiget__company">Kassy.ru</a>
       </div>
     </div>
  </div>
</template>

<script>
import vueMethods from '../../mixins/methods'
import { mapState } from 'vuex'

export default {
  name: 'allPlaces',
  mixins: [vueMethods],
  data () {
    return {
      tickets: []
    }
  },
  mounted () {
    this.$nextTick(function () {
      window.addEventListener('resize', this.updateAllPlacesOnResize)
      this.setupAllPlaces()
    })
  },
  methods: {
    setupAllPlaces () {
      let allPlaces = document.getElementById('allPlaces')
      let topRow = document.querySelector('.wiget__row--top')
      let wrapper = document.querySelector('.allPlaces__wrapper')
      let bottomRow = document.querySelector('.wiget__row--bottom')

      let allPlacesHeight = allPlaces.clientHeight
      let topRowHeight = topRow.clientHeight
      let bottomRowHeight = bottomRow.clientHeight

      let wrapperHeight = allPlacesHeight - topRowHeight - bottomRowHeight
      console.log('topRowHeight ', topRowHeight)
      console.log('allPlacesHeight ', allPlacesHeight)
      console.log('bottomRowHeight ', bottomRowHeight)
      console.log('wrapperHeight ', wrapperHeight)
      wrapper.style.minHeight = wrapperHeight + 'px'
    },
    updateAllPlacesOnResize (event) {
      this.setupAllPlaces()
    },
    getEntranceName (entrance) {
      let sectionId = entrance.section_id
      let section = this.section
      let sectionName = section.filter(function (e) {
        return e.id === sectionId
      })

      return sectionName[0].title
    },
    addTicket (index) {
      console.log(this.tickets)
      console.log(this.tickets[index])
      this.tickets[index] = parseInt(this.tickets[index]) + 1
      return this.tickets
    },
    removeTicket (index) {
      this.tickets[index] = parseInt(this.tickets[index]) - 1
    },
    addEntrancePlaceToCart (entrance, index) {
      console.log('entrance.id to add to cart ', entrance.id)
      let db = this.db
      let places = parseInt(this.tickets[index])
      console.log('places ', places)
      console.log('index ', index)
      let sessionId = this.sessionId
      let entranceId = parseInt(entrance.id)
      let params = {db, places, sessionId, entranceId}
      this.$store.dispatch('addEntrancePlaceToCart', params) // Добавили место в корзину
    },
    goToHall () {
      this.$store.dispatch('closeAllPlaces')
      this.$store.dispatch('openHallPlan')
    },
    hideLabel (e, index) {
      console.log('CLICKED')
      console.log('index click', index)
      let input = document.getElementsByClassName('allPlaces__input')
      let target = e.target
      input[index].focus()
      console.log('this.tickets ', this.tickets)
      console.log(target)
      if (this.tickets === '') {
        target.style.display = 'block'
      } else {
        target.style.display = 'none'
      }
    },
    showLabel (e, index) {
      console.log('BLUR')
      console.log('index blur', index)
      let label = document.getElementsByClassName('allPlaces__label allPlaces__label--input')
      console.log(this.tickets[index])
      if (this.tickets[index] === '' || this.tickets[index] === undefined) {
        label[index].style.display = 'block'
      } else {
        label[index].style.display = 'none'
      }
    }
  },
  destroyed () {
    window.removeEventListener('resize', this.setupAllPlaces)
  },
  computed: {
    ...mapState({
      db: state => state.onload.currentDb,
      currentEvent: state => state.onload.currentEvent,
      modals: state => state.modals,
      metric: state => state.onload.eventData.metric,
      section: state => state.onload.eventData.section,
      show: state => state.onload.eventData.show,
      event: state => state.onload.eventData.event,
      building: state => state.onload.eventData.building,
      hall: state => state.onload.eventData.hall,
      places: state => state.onload.eventData.places,
      placesSeated: state => state.onload.eventData.places.place,
      sessionId: state => state.cart.sessionId,
      ticketsInCart: state => state.cart.ticketsInCart
    })
  }
}
</script>

<style scoped lang="stylus">
@import '../../styles/Root/allPlaces'
@import '../../styles/Root/wiget'
</style>

пожалуйста, порекомендуйте

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


person Evgeny Ladyzhenskiy    schedule 07.05.2019    source источник
comment
v-bind:id="tickets" - плохая идея. Все данные будут вводиться с одним и тем же идентификатором.   -  person mathk    schedule 07.05.2019
comment
@mathk Спасибо, но это не та проблема, которую мне действительно нужно решать (   -  person Evgeny Ladyzhenskiy    schedule 07.05.2019
comment
Как вы инициализировали объект билетов? Когда места заселяются?   -  person mathk    schedule 07.05.2019
comment
Вам действительно нужны 2 кнопки, потому что базовый <input type="number"> в HTML имеет кнопки вверх / вниз?   -  person Core972    schedule 07.05.2019
comment
@mathk Пользователь мог ввести количество билетов прямо в поле ввода или изменить сумму с плюсом или минусом.   -  person Evgeny Ladyzhenskiy    schedule 07.05.2019
comment
@ Core972 Да, мне это очень нужно. Я добавил экран для лучшего понимания   -  person Evgeny Ladyzhenskiy    schedule 07.05.2019
comment
Для меня это похоже на то, что у вас не устанавливается какой-то реактивный наблюдатель. Можете ли вы показать нам этап инициализации с запросом на выборку и так далее? Как ваши данные проталкиваются в ваши билеты?   -  person mathk    schedule 08.05.2019
comment
@mathk ОБНОВЛЕНО. Я получаю данные о билетах из API, но добавляю сумму впереди и отправляю запрос на добавление билетов в корзину. Надеюсь, это поможет   -  person Evgeny Ladyzhenskiy    schedule 08.05.2019


Ответы (1)


Ты tickets неправильно инициализирован. Данные заполнили пустой массив, но шаблон добавит новый элемент без использования способа VueJs для добавления реактивности.

То, что происходит, похоже на:

let tickets = [];
tickets[0] = ...;

В VueJs вы должны использовать push для вставки элемента в массив, не используя «разреженная реализация».

Поэтому, когда ваш places заполняется внутри вашего магазина, вы должны создать таблицу билетов исходя из его размера. Что-то похожее на следующее в наблюдателе или в другом месте в зависимости от ваших потребностей:

this.tickets = this.place.map(_ => 0);
person mathk    schedule 08.05.2019
comment
Дело в том, что если я нажимаю + в первом вводе, например, а затем помещаю любое значение в любой другой ввод, я вижу обновленное значение при первом вводе. Каждый щелчок по + добавляет +1 значение, но чтобы увидеть это значение, я должен ввести любое значение в другой ввод. И я не понимаю, почему этот. Билеты не меняются динамически .... - person Evgeny Ladyzhenskiy; 13.05.2019
comment
каждый элемент вашего билета требует правильной обработки vuejs. Обязательно инициализируйте свой массив с правильным количеством элементов. Вы пробовали то, что я говорю? - person mathk; 13.05.2019