Пользовательская проверка Vuelidate показывает ошибку на каждом элементе в $ каждый - PullRequest
1 голос
/ 03 марта 2020

У меня есть formData объект со следующей структурой:

{
  name: '',
  defaultPort: 1000,
  protocolPorts: [{
    manual_ports: []
  }]
}

manual_ports - это массив строк, который может добавляться динамически. Для каждого такого порта я хочу сделать несколько проверок с помощью Vuelidate.

formData: {
    name: { required, maxLength: maxLength(64) },
    protocolPorts: {
      $each: {
        manual_ports: {
          $each: {
            required,
            numeric,
            maxLength: maxLength(5),
            between: between(1, (Math.pow(2, 16) - 1)),
            cantBeginWithZero,
            cantBeDuplicate
          }
        }
      }
    }
  }

Последняя проверка cantBeDuplicate - я хочу проверить, что отредактированный в данный момент порт не является дубликатом какого-либо другого порта или defaultPort. Проблема в том, что он в настоящее время работает, однако он показывает ошибку в текстовом поле КАЖДОГО порта, а не только после того, которое редактируется в данный момент. Есть ли способ сделать это?

Я пробовал это до сих пор:

function cantBeDuplicate (val) {

  if (val) {
    let ports = [...this.currentProtocol.manual_ports];
    ports.splice(this.currentPortIndex, 1);
    return this.currentProtocol.manual_ports.length > 1 ?
      !ports.includes(val) :
      +this.currentProtocol.manual_ports[this.currentPortIndex] === +this.currentProtocol['default_port'] || true;
  } else {
    return true;
  }
}

... и это:

return val ?
  (!_.initial(this.currentProtocol.manual_ports).includes(val) && +this.currentProtocol['default_port'] !== +val) : true;

Вот как мой текст поля определены (они внутри v-for l oop):

<v-text-field
  v-model="protocol['manual_ports'][index]"
  :error-messages="portsErrors"
  label="Port"
  height="30"
  single-line
  flat
  dense
  required
  @click="setCurrents(protocol, index)"
  @blur="$v.formData.protocolPorts.$each[pi]['manual_ports'].$each[index].$touch()"
  @input="$v.formData.protocolPorts.$each[pi]['manual_ports'].$each[index].$touch()" />

И это вычисляемое свойство portsError:

portsErrors() {
    const errors = [];
    if ( this.currentProtocol) {
      const protocolIndex = findIndex(this.formData.protocolPorts, p => p.id === this.currentProtocol.id)

      if (!this.$v.formData.protocolPorts.$each[protocolIndex].manual_ports.$each[this.currentPortIndex].$dirty) {
        return errors;
      }
      !this.$v.formData.protocolPorts.$each[protocolIndex].manual_ports.$each[this.currentPortIndex].numeric && errors.push('Digits only')
      !this.$v.formData.protocolPorts.$each[protocolIndex].manual_ports.$each[this.currentPortIndex].maxLength && errors.push('Max 5 digits')
      !this.$v.formData.protocolPorts.$each[protocolIndex].manual_ports.$each[this.currentPortIndex].between && errors.push('Range: 1 - 65535')
      !this.$v.formData.protocolPorts.$each[protocolIndex].manual_ports.$each[this.currentPortIndex].cantBeginWithZero && errors.push('No leading 0')
      !this.$v.formData.protocolPorts.$each[protocolIndex].manual_ports.$each[this.currentPortIndex].cantBeDuplicate && errors.push('No duplicates')
      !this.$v.formData.protocolPorts.$each[protocolIndex].manual_ports.$each[this.currentPortIndex].required && errors.push('Required')
    }
    return errors
  },

Возможно ли показать сообщение об ошибке только под редактируемым портом?

1 Ответ

0 голосов
/ 09 марта 2020

ОК, я нашел решение: вот основная причина, по которой это происходит, и я цитирую себя:

они внутри v-for l oop

Поскольку v-text-field внутри v-for l oop - конечно, каждый элемент в этом l oop будет иметь одинаковые проверки. Решение состояло в том, чтобы обернуть текстовое поле в компонент обертки, передать необходимые реквизиты и запустить проверку для реквизита только внутри компонента, одновременно выдавая результат и обрабатывая его в родительском компоненте.

...