【问题标题】:veevalidate reset form typescript does not reset the formveevalidate 重置表单打字稿不会重置表单
【发布时间】:2020-11-22 15:02:43
【问题描述】:

我有一个带有 veevalidate 的表单。在表单提交时,数据被发送到父级,然后我需要重置表单。按照 veevalidate 说明,应该可以通过 $refs 重置表单。

我的应用使用 TypeScript,按照指南,我的组件如下所示:

<template>
    <div>
        <ValidationObserver v-slot="{ handleSubmit }" ref="form">
            <form :model="form" @submit.prevent="handleSubmit(onSubmit)" novalidate>
                <a-input-with-validation
                        :placeholder="placeholder"
                        :label="placeholder"
                        auto-complete="off"
                        name="comment"
                        type="text"
                        v-model="form.comment"
                        rules="required"
                />

                <a-button-submit :translation-key="$t('dict.save')"/>
            </form>
        </ValidationObserver>
    </div>
</template>

<script lang="ts">
  import { Component, Prop, Vue } from 'vue-property-decorator'
  import { ValidationObserver, ValidationProvider } from 'vee-validate'
  import { OItemCommentFormChildOutput } from '@/components/organisms/forms/OItemCommentFormInterfaces'
  import AInputWithValidation from '@/components/atoms/inputs/AInputWithValidation.vue'
  import AButtonSubmit from '@/components/atoms/buttons/AButtonSubmit.vue'

  @Component({
    components: {
      AButtonSubmit,
      AInputWithValidation,
      ValidationObserver,
      ValidationProvider
    }
  })
  export default class OItemCommentForm extends Vue {
    @Prop()
    comment?: string
    @Prop({ default: true })
    add!: boolean

    $refs!: {
      form: InstanceType<typeof ValidationObserver>;
    }
    placeholder!: string

    form: OItemCommentFormChildOutput = {
      comment: ''
    }

    mounted () {
      this.$refs.form;
    }

    created () {
      this.placeholder = String(this.add ? this.$t('dict.addComment') : this.$t('dict.editComment'))
      this.form.comment = this.comment || ''
    }

    onSubmit () {
      this.$emit('child-output', this.form as OItemCommentFormChildOutput)
      // this.form.comment = ''
      this.$refs.form.reset()
    }
  }
</script>

a-input-with-validation 组件代码(来自 veevalidate):

<template>
    <ValidationProvider
            :vid="vid"
            :name="nameAlt || name"
            :rules="rules"
            v-slot="{ errors, valid }"
    >
        <b-field
                :label="label"
                :prop="name"
                v-bind="$attrs"
                :auto-complete="autoComplete"
                :type="{ 'is-danger': errors[0], 'is-success': valid }"
                :message="errors"
        >
            <b-input
                    :name="name"
                    :type="type"
                    v-bind="$attrs"
                    :placeholder="placeholder"
                    v-model="innerValue"
                    :password-reveal="type === 'password'"
                    novalidate
            />
        </b-field>
    </ValidationProvider>
</template>

<style scoped>
    .AInputWithValidation {}
</style>

<script lang="ts">
  import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
  import { ValidationObserver, ValidationProvider } from 'vee-validate'

  @Component({
    components: {
      ValidationObserver,
      ValidationProvider
    }
  })
  export default class AInputWithValidation extends Vue {
    @Prop({ required: true })
    value!: any
    @Prop({ required: true })
    label!: string
    @Prop({ required: true })
    name!: string
    @Prop({ default: 'off' })
    autoComplete!: string
    @Prop({ default: 'text' })
    type!: string
    @Prop()
    nameAlt?: string
    @Prop()
    placeholder?: string
    @Prop()
    vid?: string
    @Prop()
    rules?: string

    innerValue = ''

    created () {
      if (this.value) {
        this.innerValue = this.value
      }
    }

    @Watch('innerValue')
    innerValueHandle (newVal) {
      this.$emit('child-output', newVal)
      this.$emit('input', newVal)
    }

    @Watch('value')
    valueValueHandle (newVal) {
      this.innerValue = newVal
    }

  }
</script>

应用程序编译得很好,所以似乎没有 TS 错误。提交时,数据会正确发出。但是当我尝试调用reset 方法时,什么也没有发生。表单未重置,输入值保持不变。如果我还将表单中的注释强制为空字符串,则会触发验证器显示错误。

如何在表单提交后重置表单并清除表单内容而不触发验证错误?

(将ref="form" 移动到表单标签上也不会做任何事情:/)

【问题讨论】:

    标签: typescript vue.js vee-validate


    【解决方案1】:

    ValidationObserverreset() 只会重置验证状态,不会重置表单字段。虽然文档包含 form-reset demo that manually clears the fields,但您也可以在 &lt;form&gt; 元素上调用 HTMLFormElement.reset() 以将字段重置为其初始值。可以从SubmitEventtarget 访问&lt;form&gt; 元素:

    export default class OItemCommentForm extends Vue {
    
      async onSubmit(e) {
        // Wait microtick for models to update before resetting validation state
        await this.$nextTick()
        this.$refs.form.reset()
    
        // Reset form in next macrotick
        setTimeout(() => e.target.reset())
      }
    }
    

    关键是在下一个macrotick 中重置表单(通过setTimeout,超时为零)。

    【讨论】:

    • 这对 veevalidate 不起作用,因为事件没有传递给提交处理程序:/
    • ValidationObserver.handleSubmit 只是在validate() 失败时提前返回。否则,它将调用给定的回调。您自己的 submit-handler 可以使用 this.$refs.form.validate() 自己完成此操作,这就是我在链接演示中展示的内容。
    • 如果您更喜欢使用handleSubmit,看起来您必须自己清除表单字段(按照 VeeValidate 文档的规定)。我不确定是否有其他解决方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-31
    • 2020-09-23
    • 2019-05-30
    • 2015-06-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多