Vuejs2 - Избегайте повторения параметров выбора поля с помощью vee-validate

Я использую плагин vee-validate для проверки. В моей форме есть поле выбора в таблице. Строки будут добавляться в таблицу динамически. Я не хочу снова и снова выбирать одну и ту же опцию выбора (столбец описания) Изображение. Следовательно, я хочу выдать ошибку типа «Выбранное описание уже существует в таблице» при использовании vee-validate. Пожалуйста, помогите мне решить эту проблему.

Вот мой код:

<template>
<div>
    <b-card>
        <div class="panel-body" id="app">
            <table class="table table-hover">
                <thead>
                    <tr>
                        <th style="width: 20px;">No.</th>
                        <th style="width: 330px;">Description</th>
                        <th style="width: 130px;" class="text-right">Charges</th>
                        <th style="width: 130px;">Total</th>
                        <th style="width: 130px;"></th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="(row, index) in rows" :key="row.qty">
                        <td>
                            {{ index +1 }}
                        </td>
                        <td>

                        <select class="form-control" v-model="row.billChgDesc" v-validate="'required|check'" :name="'billChgDesc' + index" data-vv-as="Description" @change="checkRepetation">
                            <option v-for="option in billChgDescOpt" v-bind:value="option.value" 
                                :key="option.value"> {{ option.text }} 
                            </option>
                        </select>
                        <span v-show=" errors.has('billChgDesc' + index)" class="is-danger">{{  errors.first('billChgDesc' + index) }}</span>
                        </td>

                                <td> 
                                  <input class="form-control text-right" type="text" v-model="row.charges"  data-type="currency" v-validate="'required'" :name="'charges' + index" data-vv-as="Charges" >
                                     <span v-show=" errors.has('charges' + index)" class="is-danger">{{  errors.first('charges' + index) }}</span>
                                <td>
                                    <input class="form-control text-right" :value="row.qty * row.charges" number readonly />
                                    <input type="hidden" :value="row.qty * row.charges * row.tax / 100"  number/>
                                </td>

                                <td>
                                    <button class="btn btn-primary btn-sm" @click="addRow(index)"><i class="fa fa-plus"></i></button>
                                    <button class="btn btn-danger btn-sm" @click="removeRow(index)"><i class="fa fa-minus"></i></button>
                                </td>
                            </tr>
                </tbody>
                <tfoot>
                  <tr>
                        <td colspan="3" class="text-right">TOTAL</td>
                        <td colspan="1" class="text-right"><input class="form-control text-right" v-model="delivery" number/></td>
                        <td></td>
                    </tr>
                </tfoot>
            </table>

        </div>
    </b-card>
</div>
</template>

<script>
import Vue from 'vue'
import accounting from 'accounting'

export default {

  data: function () {
    return {
        billChgDescOpt: [
            { value: '', text: 'Select' },
            { value: 'M', text: 'Maintenance Fee'},
            { value: 'W', text: 'Water Charges'},
            { value: 'P', text: 'Penalty Fee'},
            ],
        rows: [
            {qty: 5, billChgDesc: '', charges: 55.20, tax: 10},
            {qty: 19, billChgDesc: '', charges: 1255.20, tax: 20},
        ],
        grandtotal: 0,
        delivery: 40,
        selectArr:[]
    }

  },
   methods: {
        addRow: function (index) {
            try {
                this.rows.splice(index + 1, 0, {});
            } catch(e)
            {
                console.log(e);
            }
        },
        removeRow: function (index) {
            this.rows.splice(index, 1);
        },
        checkRepetation:function(){
             this.$validator.extend('check', {
                    getMessage: field => '* Slected ' + field + ' already exists',
                    validate: function(value){
                            selectArr.push(value);
                    }
    })
        }
    }
}
</script>

<style lang="scss" scoped>
.is-danger{
  color:  RED;
}
</style>

Заранее спасибо.


person Ashwini    schedule 05.06.2018    source источник


Ответы (1)


Вы на правильном пути, но нужно сделать пару изменений. Когда вы вызываете this.$validator.extend, это нужно сделать только один раз - при создании вашего компонента. Он присоединяет метод check к валидатору, поэтому каждый раз, когда у вас есть атрибут v-validate="'required|check'" в вашем HTML, он будет запускать этот метод проверки.

В вашем check валидаторе вам нужно ответить на вопрос «это значение уже выбрано». Ответ заключается в том, чтобы просмотреть this.rows и посмотреть, есть ли у кого-нибудь из них такое же свойство billChgDesc. Поскольку это находится во Vue, к моменту запуска валидатора соответствующая строка уже имеет это значение, поэтому вы хотите проверить, имеет ли это значение БОЛЕЕ одной строки. Итак, примерно так:

mounted() {
  var self = this;
  this.$validator.extend('check', {
    getMessage: field => '* Selected ' + field + ' already exists',
    validate: function(value){
      return (self.rows.filter(function(v){
        return v.billChgDesc == value;
      }).length <= 1);
    }
  });
}

Этот валидатор возвращает true, если только один элемент имеет данный value. Я использую встроенный filter метод Array (см. документы).

Вы можете увидеть пример того, как все это работает здесь: https://jsfiddle.net/ryleyb/f9q50wx4/1/

person Ryley    schedule 05.06.2018
comment
Работает. На самом деле я застрял в этой проверке, и ваша информация меня спасла. Спасибо за своевременную помощь. - person Ashwini; 06.06.2018