Проверка подлинности вычисленного имущества - PullRequest
0 голосов
/ 09 апреля 2020

В моем компоненте Vue у меня есть 3 поля чисел c, например:

data() {
    return {
        numberAdults: 0,
        numberChildren: 0,
        numberInfants: 0,
    }

, а также вычисляемое свойство:

computed: {
    numberPersons() {
        return this.numberAdults + this.numberChildren + this.numberInfants
    },

Я хочу проверить это установлен хотя бы один человек (хотя бы один взрослый или один ребенок или один младенец), но я не могу заставить это работать. Это правило проверки:

numberPersons: {
    required,
    minValue: minValue(1),
},

Если я изменю numberPersons на одно из трех полей, проверка для этого поля будет работать. Я думаю, что каким-то образом Vuelidate не знает, что такое numberPersons, но я не уверен, как это изменить.

1 Ответ

3 голосов
/ 09 апреля 2020

Вы можете создать собственный метод проверки, скажем, minNumberPersons, который просто проверяет ваше вычисленное свойство this.numberPersons:

const minNumberPersons = (value, vm) => {
    return vm.numberPersons >= 1;
};

Затем вы можете применить эти правила к различным моделям:

validations: {
  numberAdults: { numberPersons },
  numberChildren: { numberPersons },
  numberInfants: { numberPersons }
}

Предложение UX, совершенно необязательно : В дополнение к этому, поскольку вы собираетесь проверять 3 поля одновременно, имеет смысл использовать метод $v.<field>.$touch(), чтобы гарантировать, что грязное состояние всех 3 полей устанавливается на true при изменении любого из них. Вы можете просто сделать привязку @input="onInput" в своем шаблоне и добавить это к своим методам:

onInput() {
  this.$v.numberAdults.$touch();
  this.$v.numberChildren.$touch();
  this.$v.numberInfants.$touch();
},

См. Подтверждение концепции здесь. Я адаптировал его из демонстрационной JSFiddle , используемой хранилищем Vuelidate .

Vue.use(window.vuelidate.default);

const numberPersons = (value, vm) => {
  return vm.numberPersons >= 1;
};

new Vue({
  el: "#app",
  data: {
    numberAdults: 0,
    numberChildren: 0,
    numberInfants: 0,
  },
  validations: {
    numberAdults: { numberPersons },
    numberChildren: { numberPersons },
    numberInfants: { numberPersons }
  },
  computed: {
    numberPersons() {
      // Converting each to a number using the unary + operator, in case user inputs empty string
      return (+this.numberAdults) + (+this.numberChildren) + (+this.numberInfants);
    },
  },
  methods: {
    status(validation) {
      return {
        error: validation.$error,
        dirty: validation.$dirty
      }
    },

    // Optional: force validation of all number inputs when any one is changed
    onInput() {
      this.$v.numberAdults.$touch();
      this.$v.numberChildren.$touch();
      this.$v.numberInfants.$touch();
    },
  }
})
body {
  background: #fff;
}

input {
  border: 1px solid silver;
  border-radius: 4px;
  background: white;
  padding: 5px 10px;
}

.dirty {
  border-color: #5A5;
  background: #EFE;
}

.dirty:focus {
  outline-color: #8E8;
}

.error {
  border-color: red;
  background: #FDD;
}

.error:focus {
  outline-color: #F99;
}
<!-- Boilerplate adapted from Vuelidate's default demo: https://jsfiddle.net/Frizi/b5v4faqf/ -->

<script src="https://unpkg.com/vuelidate/dist/vuelidate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <input v-model.number="$v.numberAdults.$model" :class="status($v.numberAdults)" @input="onInput" type="number">
  <input v-model.number="$v.numberChildren.$model" :class="status($v.numberChildren)" @input="onInput" type="number">
  <input v-model.number="$v.numberInfants.$model" :class="status($v.numberInfants)" @input="onInput" type="number">
  <br />
  <br />
  Total number of people: <strong>{{ numberPersons }}</strong>
</div>
...