简体   繁体   English

如何修改我的自定义输入组件以使用 vee-validate?

[英]How to modify my custom input component to work with vee-validate?

I have created an input component in my Vue project and I'm using this component inside my forms.我在我的 Vue 项目中创建了一个输入组件,我在我的表单中使用了这个组件。 I wanna use vee-validate to validate my inputs.我想使用 vee-validate 来验证我的输入。

First, I tried to validate my component just like a normal input, but after failing at displaying error messages and checking Vue Devtools, I figured out that errors are scoped to the input component.首先,我尝试像普通输入一样验证我的组件,但在显示错误消息和检查 Vue Devtools 失败后,我发现错误仅限于输入组件。 (although there are two computed properties named "errors" and "fields" that all my components have access to, from root to input component itself.) (尽管我的所有组件都可以访问两个名为“errors”和“fields”的计算属性,从根到输入组件本身。)

Then I checked vee-validate docs and tried to use Validation Provider and Validation Observer .然后我检查了vee-validate 文档并尝试使用Validation ProviderValidation Observer These two components are too confusing to me and I couldn't figure out how to use them even after checking this medium article .这两个组件对我来说太混乱了,即使在查看了这篇中篇文章后,我也无法弄清楚如何使用它们。 I don't know how these components are making use of scoped slots.我不知道这些组件如何使用作用域插槽。

I wanna be able to validate input components in the parent and also display their error messages in the parent above the form.我希望能够验证父级中的输入组件,并在表单上方的父级中显示它们的错误消息。 (with or without Validation Observer and/or Validation Provider). (有或没有验证观察者和/或验证提供者)。 Any approach is appreciated.任何方法都值得赞赏。

This is my input component:这是我的输入组件:

<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>

and this is minimal version of my form with just one input component:这是我的表单的最小版本,只有一个输入组件:

<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>

PS: I have registered Validation Observer and Validation Provider globally. PS:我已经在全球范围内注册了Validation Observer和Validation Provider。

Try following this example :试试这个例子

<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>

I added only a couple things - the $_veeValidate section in the script.我只添加了几件事 - 脚本中的$_veeValidate部分。 I also changed your component to use the value prop but store the changes in a local reactive item called localValue .我还更改了您的组件以使用value道具,但将更改存储在名为localValue的本地反应项中。 Generally you won't want to change the value of a prop, although it might work in this simple of a case.通常,您不会想更改 prop 的值,尽管它可能适用于这种简单的情况。 Re-read One-Way Data Flow for details.重新阅读单向数据流以了解详细信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM