V-модель на составных данных - PullRequest
0 голосов
/ 05 июля 2018

Я новичок в Vue.js, и я хотел бы установить некоторые данные, используя двустороннюю привязку данных через v-model (на двух отдельных входах)

Зачем мне это нужно: у меня есть два ввода (input[type=number] и select, содержащие «дни», «месяцы», «годы»). И очевидно, что эти два входа будут объединены с данными.

Другое ограничение заключается в том, что пользователь может добавлять столько «периодов», сколько ему нужно, поэтому данные представляют собой строку в массиве. Используя v-for="(period, index) in periods", легко нацелиться на заданный индекс в массиве данных, но это становится сложным, если мне нужно использовать computed с get(), взрывающим значение, и set(), объединяющим их ... Но если нет более легкого магического пути, мне придется придерживаться его ...

Пример HTML:

<agreement inline-template>
    <div v-for="(period, index) in ftc_trial_periods">    
        <input type="number" min="1" v-model="??" required>

        <select v-model="??" required>
            <option>days</option>
            <option>months</option>
            <option>years</option>
        </select>
    </div>
</agreement>

Пример компонента:

Vue.component('agreement', {
    data() {
        return {
            ftc_trial_periods: []
        }
    }
});

Когда число изменяется или когда выбирается опция, я бы хотел, чтобы значение было конкатенировано / установлено / добавлено в ftc_trial_periods. Например, ftc_trial_periods может быть: ['1 day', '3 months'].

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Генерация <select> на основе <input> с проверкой

Решением вашей проблемы было бы использование вычисленного значения для создания periods и итерации по этому значению для создания нескольких выборок с v-for='index in period, отсюда нам нужно динамически связывать значение каждого выбора в массиве selectedArray: ['']. Для этого я использую вычисленное свойство periods, чтобы проверить изменение количества периодов в строке по сравнению с длиной selectedArray. Если есть больше периодов, я .push другую строку на selectedArray, если есть меньше, я .pop последний выключен. Чтобы связать каждый элемент выбора, я использую v-bind='selectedArray[index]. Наконец, мы проверяем строку и проверяем, что каждый выбор заполнен, если это так, все данные объединяются в массив строк.

Вот код (ниже и в JSFiddle):

Код Vue.js:

Vue.component('agreement', {
  template: `
    <div>    
      <input
        type="text"
        v-model="numbers"
      />
      <select
        v-for='index in periods'
        v-model='selectedArray[index - 1]'
        required
      >
        <option>days</option>
        <option>months</option>
        <option>years</option>
      </select>
      <p>
        {{ output }}
      </p>
    </div>
  `,
  data: () => ({
    numbers: '',
    selectedArray: ['']
  }),
  computed: {
    inputsAreValid: function() {
      return this.numbers.match(/^\d+((\.\d+)?)+$/g) && this.selectedArray.every(selection => selection !== '')
    }, 
    output: function() {
      if (!this.inputsAreValid)
        return []
      return this.numbers.split('.').map((number, index) => `${number} ${this.selectedArray[index]}`)
    },
    periods: function() {
      const numberOfPeriods = this.numbers.split('.').length
      if (numberOfPeriods > this.selectedArray.length)
        this.selectedArray.push('')
      else if (numberOfPeriods < this.selectedArray.length)
        this.selectedArray.pop()
      return numberOfPeriods
    }
  }
})

new Vue({
  el: "#app"
})

HTML-код шаблона:

<div id="app">
  <agreement></agreement>
</div>
0 голосов
/ 05 июля 2018

В этом сценарии я бы сохранил значения формы в данных и сделал бы ftc_trial_periods вычисленное значение этих данных. Таким образом, взрыв / соединение не требуется.

https://jsfiddle.net/jacobgoh101/kgodqmbx/6/

<div id="app">
    <button @click="addPeriod">add period</button><br><br>
    <div v-for="(form) in formInputs">    
        <input type="number" min="1" v-model="form.value" required>

        <select v-model="form.type" required>
            <option>days</option>
            <option>months</option>
            <option>years</option>
        </select>
    </div>
    ftc_trial_periods: {{ftc_trial_periods}}
</div>
new Vue({
  el: "#app",
  data: {
    formInputs: [
        {
        value: null,
        type: null
      }
    ]
  },
  computed: {
    ftc_trial_periods: function() {
        return this.formInputs.map(obj => {
        return `${obj.value} ${obj.type}`;
      });
    }
  },
  methods: {
    addPeriod: function() {
        this.formInputs.push({
        value: null,
        type: null
      });
    }
  }
})
...