Как DRY up VueJS + код ошибки проверки на стороне сервера Vuelidate? - PullRequest
0 голосов
/ 03 августа 2020

Я работаю над проектом VueJS (используя фреймворк Quasar). При создании компонента формы, например, для редактирования пользовательских настроек, у меня есть проверка внешнего интерфейса, чтобы проверить обязательные поля и т. Д. c. используя vuelidate, и я также хочу показать ошибки проверки серверной части. В настоящее время моя установка (для образца формы) выглядит следующим образом:

сценарий:

export default {
  name: 'UserEditForm',
  mixins: [formServerValidation],
  data: function () {
    return {
      form: {
        ...
        name: this.$store.state.currentUser.attributes.name,
        currentPassword: 'winnerwinner',
        serverErrors: {
          // Todo: Autogenerate all server errors
        }
      }
    }
  },
  methods: {
    onSubmit () {
      const name = this.form.name
      const currentPassword = this.form.currentPassword
      this.clearServerErrors()


      this.$store.dispatch('updateUser', { name, currentPassword, }).then((result) => {
        console.log("Server update success")
      }).catch(err => {
        console.log("Server update error")
        const mappedErrors = this.mapServerErrors(err.response.data.errors)
        merge(this.form.serverErrors, mappedErrors)
        this.$refs.form.validate()
      })
    },
    serverError: function (fieldName) {
      return (value, vm) => {
        return !(
          Object.prototype.hasOwnProperty.call(vm, 'serverErrors') &&
          Object.prototype.hasOwnProperty.call(vm.serverErrors, fieldName)
        )
      }
    }
  },
  validation: {
    form: {
      ...
      name: {
        required,
        serverError: this.serverError('name')
      },
      currentPassword: {
        required,
        serverError: this.serverError('currentPassword')
      },
      ...
    }
  }
}

шаблон:

<template>
<q-form @submit="onSubmit" ref="form">
  ...
  <q-input
    field-name="name"
    type="text"
    v-model="form.name"
    label="Name"
    lazy-rules
    @input="clearServerError('name', $event)"
    :rules="[
      val => $v.form.name.required || 'Enter name',
      val => $v.form.name.serverError || form.serverErrors.name,
    ]" />

  <q-input
    field-name="currentPassword"
    type="password"
    v-model="form.currentPassword"
    label="Current password*"
    lazy-rules
    @input="clearServerError('currentPassword', $event)"
    :rules="[
      val => $v.form.currentPassword.required || 'Confirm password',
      val => $v.form.currentPassword.serverError || form.serverErrors.currentPassword
    ]"
    />
  ...
  <div>
    <q-btn label="Save" type="submit" color="primary" />
  </div>
</q-form>
</template>

Все это работает отлично, но кажется очень ВЛАЖНЫМ (не DRY). Я должен определить следующее для каждого поля вручную :

  1. serverError: this.serverError('name') в validation
  2. Правило val => $v.form.name.serverError || form.serverErrors.name в шаблоне
  3. @input="clearServerError('name', $event)" в шаблоне

Но я знаю, что хочу сделать это для каждого ввода в моем компоненте формы, поэтому делать это вручную очень часто. для каждого входного компонента. Есть ли правильный способ «Vue -i sh» для DRY этого?

Я пытался найти все поля ввода, пройдя по всем потомкам моего компонента формы, используя $children . Затем:

Я попытался решить 1., динамически определяя эти ошибки сервера, перебирая все входные компоненты.

2. труднее справиться, так как вы не можете напрямую обновить свойство :rules, поскольку Vue переопределит его при новом рендере родительского компонента. (Это также вызывает предупреждение, в котором говорится, что вам не следует напрямую обновлять свойства, а использовать v-model et c.)

Я пытался решить 3., динамически определяя прослушиватели событий ввода из моего компонента формы, используя метод $on на фактических компонентах ввода.

Метод DRY для 1 и 3, кажется, работает, но лучший ли это способ сделать это? А как правильно сушить 2?

...