itsource

vuelidate를 사용하여 중첩된 개체를 검증할 때 오류 메시지를 vuetify로 표시

mycopycode 2022. 8. 28. 09:57
반응형

vuelidate를 사용하여 중첩된 개체를 검증할 때 오류 메시지를 vuetify로 표시

vuelidate를 사용하여 폼 입력을 확인하고 vuetifyjs를 사용하여 오류 메시지를 표시하고 있습니다.기본적인 오브젝트 검증을 실시해, 에러 메세지를 표시할 수 있었습니다.

그러나 수집을 검증할 때 오류 메시지를 표시하는 데 문제가 있습니다.

쟁점.

데이터 구조 예:

contact: {
  websites: [
    {
      url: 'http://www.something.com',
      label: 'Website',
    }
  ]
}

검증 예:

validations: {
  websites: {
    $each: {
      url: {
        url,
      }
    }
  },
}

샘플 템플릿:

<template v-for="(website, index) in websites">
        <v-layout row :key="`website${index}`">
          <v-flex xs12 sm9 class="pr-3">
            <v-text-field
                    label="Website"
                    :value="website.url"
                    @input="$v.websites.$touch()"
                    @blur="$v.websites.$touch()"
                    :error-messages="websiteErrors"
            ></v-text-field>
          </v-flex>
        </v-layout>
</template>

계산된 오류 메시지의 예:

websiteErrors() {
        console.log('websites',this.$v.websites) // contains $each
        const errors = []
        if (!this.$v.websites.$dirty) {
          return errors
        }
        // Issue is that all of them show must be valid, even if they are valid. 
        // Validation is basically broken.
        // I also tried this.$v.websites.$each.url
        !this.$v.websites.url && errors.push('Must be valid url')
        return errors
      },

예제 메서드(Update, 통과 인덱스를 사용하여 시도된 메서드):

websiteErrors(index) {
        console.log('this.$v.entity.websites', this.$v.entity.websites.$each.$iter, this.$v.entity.websites.$each.$iter[index], this.$v.entity.websites.minLength, this.$v.entity.websites.$each.$iter[index].url)
        const errors = []
        if (!this.$v.entity.websites.$dirty) {
          return errors
        }

        !this.$v.entity.websites.$each.$iter[index].url && errors.push('Must be valid url')
        return errors
      },

그러나 이렇게 하면 항상 참이기 때문에 오류가 나타나지 않습니다.

기대됩니다

vuelidate 서브 컬렉션 검증과 같은 예를 사용하고 싶습니다.템플릿에서 루프를 하는 대신 프로그래밍 방식으로 메시지를 생성하려고 합니다.

언급

vuelidate에서 제공하는 예:

import { required, minLength } from 'vuelidate/lib/validators'

export default {
  data() {
    return {
      people: [
        {
          name: 'John'
        },
        {
          name: ''
        }
      ]
    }
  },
  validations: {
    people: {
      required,
      minLength: minLength(3),
      $each: {
        name: {
          required,
          minLength: minLength(2)
        }
      }
    }
  }
}

<div>
  <div v-for="(v, index) in $v.people.$each.$iter">
    <div class="form-group" :class="{ 'form-group--error': v.$error }">
      <label class="form__label">Name for {{ index }}</label>
      <input class="form__input" v-model.trim="v.name.$model"/>
    </div>
    <div class="error" v-if="!v.name.required">Name is required.</div>
    <div class="error" v-if="!v.name.minLength">Name must have at least {{ v.name.$params.minLength.min }} letters.</div>
  </div>
  <div>
    <button class="button" @click="people.push({name: ''})">Add</button>
    <button class="button" @click="people.pop()">Remove</button>
  </div>
  <div class="form-group" :class="{ 'form-group--error': $v.people.$error }"></div>
  <div class="error" v-if="!$v.people.minLength">List must have at least {{ $v.people.$params.minLength.min }} elements.</div>
  <div class="error" v-else-if="!$v.people.required">List must not be empty.</div>
  <div class="error" v-else-if="$v.people.$error">List is invalid.</div>
  <button class="button" @click="$v.people.$touch">$touch</button>
  <button class="button" @click="$v.people.$reset">$reset</button>
  <tree-view :data="$v.people" :options="{rootObjectKey: '$v.people', maxDepth: 2}"></tree-view>
</div>

잘못된 점

  1. 모든 형제자매가 동일한 오류 메시지를 공유하는 문제를 일으키는 공유 계산된 속성입니다.(인라인으로 쓰면 해결)
  2. 어레이가 "반응적"으로 업데이트되지 않아 반응성이 트리거되지 않습니다(이 경우 인덱스를 업데이트하는 대신 변경 감지 경고에 유의하십시오. 어레이를 복사하고 항목을 교체한 후 어레이 전체를 설정합니다).
  3. 잘못된 사용 장소vuelidate $each.$iter: 계산된 오류 메시지에서 로 이동했습니다.v-for

솔루션

방법은 다음과 같습니다(수정 1 및 3).

<template v-for="(v, index) in $v.websites.$each.$iter">
  <v-layout row :key="`website${index}`">
    <v-flex xs12 sm9 class="pr-3">
      <v-text-field
                    label="Website"
                    :value="v.$model.url"
                    @input="$v.websites.$touch()"
                    @blur="$v.websites.$touch()"
                    :error-messages="v.$dirty && !v.required ? ['This field is required'] : !v.url ? ['Must be a valid url'] : []"
      />
    </v-flex>
  </v-layout>
</template>

현재 업데이트 방법(수정 2)은 다음과 같습니다.

  updateWebsite(index, $event) {
    const websites = [...this.websites];
    websites[index] = $event;
    this.updateVuex(`websites`, websites)
    this.$v.websites.$touch()
  },

원래 이랬습니다.

  updateWebsite(index, $event) {
    this.updateVuex(`websites[${index}]`, $event)
    this.$v.websites.$touch()
  },

대안

또 다른 옵션이 있습니다.이 경우 랩하는 것입니다.website컴포넌트 내부에 있습니다.이렇게 하면 계산된 오류 메시지가 공유되지 않으므로 메시지를 유지할 수 있습니다.

언급URL : https://stackoverflow.com/questions/51124418/displaying-error-messages-in-vuetify-when-validating-nested-object-with-vuelidat

반응형