Как изменить мой пользовательский компонент ввода для работы с vee-validate?

Я создал компонент ввода в моем проекте Vue, и я использую этот компонент в своих формах. Я хочу использовать vee-validate для проверки моих входных данных.

Сначала я попытался проверить свой компонент так же, как обычный ввод, но после того, как не смог отобразить сообщения об ошибках и проверить Vue Devtools, я понял, что ошибки относятся к компоненту ввода. (хотя есть два вычисляемых свойства с именами «ошибки» и «поля», к которым имеют доступ все мои компоненты, от корневого до самого входного компонента.)

Затем я проверил vee-validate docs и попытался использовать провайдер проверки и Validation Observer. Эти два компонента меня слишком сбивают с толку, и я не мог понять, как их использовать даже после проверки в этой статье. Я не знаю, как эти компоненты используют слоты с ограниченной областью видимости.

Я хочу иметь возможность проверять входные компоненты в родительском элементе, а также отображать их сообщения об ошибках в родительском элементе над формой. (с наблюдателем за валидацией и / или поставщиком валидации или без них). Любой подход приветствуется.

Это мой входной компонент:

<template>
  <div class="info-input-control">
    <div class="info-input-icon">
      <slot name="icon"><span uk-icon="icon: pencil; ratio: 1.4"></span></slot>
    </div>

    <input :id="id" :type="type" :value="value" :name="name"
           v-validate="validations || ''"
           @keyup.enter="$emit('enter')"
           @focus="isActive = true"
           @blur="isActive = value.length > 0"
           @input="$emit('input', $event.target.value)" :key="name">
    <label :for="id" :class="{'info-input-label': true, 'is-active': isActive}">{{label}}</label>

  </div>
</template>

<script>
    export default {
        name: 'InfoTextInput',
        props: {
            id: String,
            label: String,
            ltr: Boolean,
            name: {
                type: String,
                required: true
            },
            type: {
                type: String,
                required: true,
                validator: function (value) {
                    return ['text', 'password', 'email'].indexOf(value) !== -1
                }
            },
            validations: Object,
            value: String
        },
        data() {
            return {
                isActive: false
            }
        },
        mounted() {
            this.isActive = this.value.length > 0
        }
    }
</script>

и это минимальная версия моей формы с одним входным компонентом:

<form action="#" @submit.prevent="userLogin">
    <div class="uk-text-danger">
        <span>Errors: </span>
        <span>{{errors.first('mobile')}}</span>
    </div>

    <div class="uk-flex uk-flex-center">
        <div class="uk-width-medium">
            <info-text-input type="text" id="user-login-phone" label="Mobile" name="mobile" ltr v-model="login.mobile" :validations="mobileValidations" key="login-mobile">
                <template v-slot:icon>
                    <span uk-icon="icon: phone; ratio: 1.4"></span>
                </template>
            </info-text-input>
        </div>
    </div>
</form>

P.S: Я зарегистрировал наблюдателя за валидацией и провайдер валидации во всем мире.


person amirify    schedule 20.06.2019    source источник


Ответы (1)


Попробуйте выполнить этот пример:

<template>
  <div class="info-input-control">
    <div class="info-input-icon">
      <slot name="icon"><span uk-icon="icon: pencil; ratio: 1.4"></span></slot>
    </div>

    <input :id="id" :type="type" :name="name"
           v-model="localValue"
           v-validate="validations || ''"
           @keyup.enter="$emit('enter')"
           @focus="isActive = true"
           @blur="isActive = value.length > 0"
           @input="$emit('input', localValue)" :key="name">
    <label :for="id" :class="{'info-input-label': true, 'is-active': isActive}">{{label}}</label>

  </div>
</template>

<script>
    export default {
        $_veeValidate: {
           value() {
               return this.localValue;
           },
           name() {
              return this.name;
           }
        },
        name: 'InfoTextInput',
        props: {
            id: String,
            label: String,
            ltr: Boolean,
            name: {
                type: String,
                required: true
            },
            type: {
                type: String,
                required: true,
                validator: function (value) {
                    return ['text', 'password', 'email'].indexOf(value) !== -1
                }
            },
            validations: Object,
            value: String
        },
        data() {
            return {
                localValue: this.value,
                isActive: false
            }
        },
        mounted() {
            this.isActive = this.localValue.length > 0
        }
    }
</script>

Я добавил всего пару вещей - раздел $_veeValidate в скрипте. Я также изменил ваш компонент, чтобы использовать опору value, но сохранил изменения в локальном реактивном элементе под названием localValue. Обычно вы не хотите изменять значение опоры, хотя в этом простом случае это может сработать. Прочтите еще раз Односторонний поток данных. для подробностей.

person Ryley    schedule 20.06.2019