veevalidate 重置表单打字稿不会重置表单

Posted

技术标签:

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

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

设置参考: https://logaretm.github.io/vee-validate/guide/forms.html#programmatic-access-with-refs 使用以下命令重置表单: https://logaretm.github.io/vee-validate/api/validation-observer.html#methods

我的应用使用 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" 移动到表单标签上也不会做任何事情:/)

【问题讨论】:

【参考方案1】:

ValidationObserverreset() 只会重置验证状态,不会重置表单字段。虽然文档包含 form-reset demo that manually clears the fields,但您也可以在 &lt;form&gt; 元素上调用 HTMLFormElement.reset() 以将字段重置为其初始值。可以从SubmitEvent 的target 访问&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 文档的规定)。我不确定是否有其他解决方法。

以上是关于veevalidate 重置表单打字稿不会重置表单的主要内容,如果未能解决你的问题,请参考以下文章

为啥重置表单不会清除绑定的模型属性

jQuery 不显眼的表单验证器在重置表单时不会隐藏错误消息

为什么重置表单不会清除绑定的模型属性

Angular NgForm:重置确切的表单字段值不会使其有效

使用 jQuery 重置多阶段表单

使用 jQuery 重置多阶段表单