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

veevalidate reset form typescript does not reset the form

我有一个带有 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" 移动到表单标签上也没有任何作用:/)

ValidationObserverreset() 仅重置验证状态,不重置表单字段。虽然文档包含 form-reset demo that manually clears the fields, you could alternatively invoke HTMLFormElement.reset() on the <form> element to reset the fields to their initial values. The <form> element can be accessed from the SubmitEvent's target:

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 零超时)。