Событие Vue js не получено

Я только начал экспериментировать с vue js и создаю с его помощью форму оформления заказа. Я также использую Symfony 31 для проекта. На странице оформления заказа / регистрации у меня есть встроенная коллекция форм, представляющих элементы заказа (каждая из которых является подпиской на тип продукта). Вы можете выбрать несколько элементов, установив флажок. Вы также можете изменить количество. К сожалению, мне не удается передать обновление количества экземпляру Vue. Записи регистрируются при рендеринге с количеством 1, и если я изменяю количество, а затем выбираю элемент, цена рассчитывается правильно, но приложение регистрирует это как новую сущность. Привязка к количеству не работает. Мне также нужно будет добавить аналогичное поле под названием частота, и я знаю, что у меня будет такая же проблема. Помощь?

Вот скрипт js: https://jsfiddle.net/wavsu8xm/

Javascript:

var bus = new Vue();

var entriesComponent = Vue.component('entries', {
  template: '#entries',
  props: {
    entries: [Array, Object],
    selected: Array,
    addons: Array,
    frequencies: [Array, Object],
  },
  watch: {
    selected: function(val, oldVal) {
      bus.$emit('selected-changed', val);
    },
  }
});

new Vue({
  el: '#app',
  data: {
    entries: [],
    selected: [],
    addons: [],
    frequencies: [],
    paymentConfig: {
      advance: 25,
      firstweek: 25,
      ondelivery: 50,
    },
    weeks: 12,
  },
  components: {
    'entriesComponent': entriesComponent,
  },
  created: function() {
    // store this to use with Vue.set
    var temp = this;
    bus.$on('selected-changed', function(selected) {
      // vm.$set deprecated
      Vue.set(temp, 'selected', selected);
    });
  },
  computed: {
    totalAdvance: function() {
      return (this.paymentConfig.advance * this.total) / 100;
    },
    totalFirstWeek: {
      get: function() {
        return (this.paymentConfig.firstweek * this.total) / 100;
      },
    },
    onDeliveryPayment: {
      get: function() {
        return (this.paymentConfig.ondelivery * this.total) / (this.weeks * 100);
      }
    },
    total: {
      get: function() {
        var sum = 0;
        var weeks = this.weeks;
        this.selected.forEach(function(item) {
          sum += weeks * item.itemPrice * item.quantity;
        });
        console.log(sum);
        return sum;
      }
    }
  }
});

Шаблон:

<section class="content">
  <div class="row" id="app">
    <div class="col-md-8">
      <div class="box box-primary">
        <div class="box-body">
          <div class="row">
            <div class="col-md-12">
              <div class="form-group">
                <label class="control-label required">Items</label>
                <div class="col-md-12">
                  <entries :entries="{ 0 : { shareSize : 'Small', quantity : '1', itemPrice : '24', frequency : '' }, 1 : { shareSize : 'Medium', quantity : '1', itemPrice : '35', frequency : '' }, 2 : { shareSize : 'Large', quantity : '1', itemPrice : '46', frequency : '' } }"
                  :selected="selected"></entries>
                  <!-- component template -->
                  <template id="entries">
                    <div class="col-md-12">
                      <div class="form-group" v-for="(entry, key) in entries" v-bind:entry="entry">
                        <div class="form-group col-md-12">
                          <div class="col-md-12">
                            <div class="col-md-4">
                              <input type="checkbox" v-bind:value="entry" v-model="selected">
                            </div>
                            <div class="col-md-4">{{entry.shareSize}}</div>
                            <div class="col-md-4">{{'$ ' + Number(entry.itemPrice).toFixed(2) }}</div>
                          </div>
                          <div class="form-group col-md-12">
                            <div class="col-md-6">
                              <input type="number" v-model="entry.quantity" :value="entry.quantity" />
                            </div>
                          </div>

                        </div>
                      </div>
                    </div>
                  </template>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="col-md-4">
        <div class="box box-info">
          <div class="box-body" style="padding:15px;">
            <div class="container-fluid">
              <div class="form-group">
                <div class="control-label">
                  <label>Summary</label>
                </div>
                <div class="form-control" v-for="item in selected">
                  <span class="pull-left small-box-footer">{{ item.shareSize }}</span>
                  <span class="pull-right">{{ item.quantity + ' x $ ' + (item.itemPrice*item.quantity).toFixed(2)}}</span>
                </div>
                <div class="control-label">
                  <label>Payment plan</label>
                </div>
                <div class="col-md-12">
                  {{ '$ ' + totalAdvance.toFixed(2) }} - advance
                </div>
                <div class="col-md-12">
                  {{ '$ ' + totalFirstWeek.toFixed(2) }} - first week
                </div>
                <div class="col-md-12">
                  {{ '$ ' + onDeliveryPayment.toFixed(2) }}/ week on each of the {{ weeks }} weeks of the subscription
                </div>
                <div class="col-md-12 row">
                  <div class="control-label"><strong><span class="pull-left">Total</span><span class="pull-right">{{ '$ ' + total.toFixed(2) }}</span></strong></div>
                </div>
                <div class="col-md-12 row">
                  <div class="title"><strong><span class="pull-left">Total due now</span><span class="pull-right">{{ '$ ' + totalAdvance.toFixed(2) }}</span></strong></div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

person alexandra    schedule 22.11.2016    source источник


Ответы (1)


Вы изменяете свои реквизиты напрямую, которые будут перезаписаны при повторном рендеринге родительского компонента, поэтому вам нужно сделать их копию внутри вашего компонента, что можно сделать внутри созданного метода вашего компонента:

  created: function() {
    // copy props to data
    this.entriesCopy = this.entries;
    this.selectedCopy = this.selected;
  },
  data: function() {
    return{
     entriesCopy: [],
     selectedCopy: []
    }
  }

Теперь вам просто нужно обновить свой наблюдатель:

  watch: {
    selectedCopy: function(val, oldVal) {
      bus.$emit('selected-changed', val);
    }
  }

И ваш шаблон:

//...
div class="form-group" v-for="(entry, key) in entriesCopy" v-bind:entry="entry">
//...
<input type="checkbox" v-bind:value="entry" v-model="selectedCopy">

чтобы отразить изменения.

Вот обновленный jsfiddle: https://jsfiddle.net/5pyw74h9/

person craig_h    schedule 22.11.2016
comment
Огромное спасибо! Теперь это работает! Незначительное обновление: data () {должно быть записано data: function () { - person alexandra; 22.11.2016
comment
Да, извините, я использую синтаксис Ecmascript 6, который нужно скомпилировать с помощью чего-то вроде babel для использования в браузере, я Я обновлю ответ и вместо этого буду использовать Ecmascript 5. - person craig_h; 22.11.2016
comment
У меня есть еще вопрос. Стоит добавить сюда или сделать новый? Скажем, я хочу добавить на страницу два элемента типа ‹entries› (один и тот же компонент), но я хочу, чтобы они оба записывались в один и тот же выбранный массив. (Выбранное свойство на главном экране должно быть объединением двух элементов) - person alexandra; 22.11.2016
comment
@anegrea, не могли бы вы опубликовать это в новом вопросе, поскольку здесь будет сложно ответить на него. :) - person craig_h; 22.11.2016
comment
stackoverflow.com/ questions / 40746450 / Заранее большое спасибо! - person alexandra; 22.11.2016