Vee 验证 - 重复表单 - 复选框

Vee validate - repeat form - checkbox

我有一个简单的表单,其中包含一些用于捕获联系方式的输入。可以使用提供的添加按钮重复该表格。如果要添加多个联系人,用户必须 select 一个主要联系人。我有一个自定义验证器。 当添加几行并取消 select 所有主要联系人复选框然后 select 一个时,我的问题就出现了。 - 在这一点上,我希望之前显示的所有错误都消失。出于某种原因,双向数据绑定似乎不起作用,或者我一定是做错了什么。假设我在其他字段上有更多验证,我如何才能避免与主要联系人复选框相关的验证错误?

<template>
  <div id="app">
    <b-col md="12">
      <ValidationObserver ref="contactValidation">
        <b-row
          v-for="(item, index) in contactDtos"
          :id="item.id"
          :key="item.id"
          ref="row"
        >
          <b-col md="3">
            <!-- First Name -->
            <b-form-group>
              <ValidationProvider
                #default="{ errors }"
                name="First name"
                vid="FirstName"
              >
                <b-form-input
                  id="'firstName' + item.id"
                  v-model="item.firstName"
                  :state="errors.length > 0 ? false : null"
                  placeholder="First Name"
                />
                <small class="text-danger">{{ errors[0] }}</small>
              </ValidationProvider>
            </b-form-group>
          </b-col>
          <b-col md="3">
            <!-- Last Name -->
            <b-form-group>
              <ValidationProvider
                #default="{ errors }"
                name="Last name"
                vid="LastName"
              >
                <b-form-input
                  id="'lastName' + item.id"
                  v-model="item.lastName"
                  :state="errors.length > 0 ? false : null"
                  placeholder="Last Name"
                />
                <small class="text-danger">{{ errors[0] }}</small>
              </ValidationProvider>
            </b-form-group>
          </b-col>
          <b-col md="3" class="mt-2">
            <!-- Primary contact -->
            <b-form-group>
              <ValidationProvider
                #default="{ errors }"
                :rules="{ chk_primary_contact: [contactDtos, item.id] }"
                name="Primary contact"
                vid="PrimaryContact"
              >
                <b-form-checkbox
                  v-model="item.primaryContact"
                  :checked="item.primaryContact"
                  :state="errors.length > 0 ? false : null"
                >
                  Primary contact
                </b-form-checkbox>
                <small class="text-danger">{{ errors[0] }}</small>
              </ValidationProvider>
            </b-form-group>
          </b-col>
          <b-col md="2" class="mt-2">
            <b-row>
              <b-col v-if="index + 1 == contactDtos.length" cols="6">
                <b-button
                  :v-if="false"
                  variant="outline-primary"
                  class="rounded-circle"
                  @click="contactFormRepeat"
                >
                  Add
                </b-button>
              </b-col>
              <b-col
                v-if="index + 1 == contactDtos.length && contactDtos.length > 1"
                cols="6"
              >
                <b-button
                  variant="outline-danger"
                  class="rounded-circle"
                  @click="removeContactForm(index)"
                >
                  Delete
                </b-button>
              </b-col>
            </b-row>
          </b-col>
          <b-col cols="12">
            <hr />
          </b-col>
        </b-row>
      </ValidationObserver>
    </b-col>
  </div>
</template>

<script>
import { extend, ValidationProvider, ValidationObserver } from "vee-validate";
import {
  BRow,
  BCol,
  BFormGroup,
  BFormInput,
  BFormCheckbox,
  BButton,
  // BFormInvalidFeedback,
} from "bootstrap-vue";

export const validatorPrimaryContact = (chkValue, [contactDtos, id]) => {
  console.log(id);
  if (contactDtos === undefined || id === undefined) return true;

  if (chkValue) {
    contactDtos.forEach((x) => {
      if (x.id !== id) {
        // remove if multiple check boxes are checked.
        x.primaryContact = false;
      }
    });
    const contactCount = contactDtos.filter((x) => x.primaryContact === true);
    if (contactCount.length === 1) {
      return true;
    }
    return false;
  } else {
    const contactCount = contactDtos.filter((x) => x.primaryContact === true);
    if (contactCount.length === 0) {
      return false;
    } else {
      return true;
    }
  }
};

extend("chk_primary_contact", {
  validate: validatorPrimaryContact,
  message: "Please select a primary contact",
});

export default {
  name: "App",
  components: {
    ValidationProvider,
    ValidationObserver,
    BRow,
    BCol,
    BFormGroup,
    BFormInput,
    BFormCheckbox,
    BButton,
  },
  data() {
    return {
      contactDtos: [
        {
          id: 1,
          firstName: "",
          LastName: "",
          primaryContact: true,
        },
      ],
    };
  },
  methods: {
    contactFormRepeat() {
      const { length } = this.contactDtos;
      this.contactDtos.push({
        id: length + 1,
        firstName: "",
        lastName: "",
        contactEmail: "",
        contactPhone: "",
        primaryContact: false,
      });
    },
    removeContactForm(index) {
      this.contactDtos.splice(index, 1);
      if (this.contactDtos.length === 1) {
        this.contactDtos[0].primaryContact = true;
      }
    },
  },
};
</script>

<style>
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

请找到沙盒here

非常感谢任何帮助!

你找到解决办法了吗? 由于不会触发除您单击的复选框以外的其他复选框, 自己手动删除错误如何?

为复选框验证提供程序提供一个 ref 并在触发复选框时 删除其他复选框错误。像这样...

template:

<ValidationProvider
                :ref="`PrimaryContact${index}`"
                #default="{ errors }"
                :rules="{ chk_primary_contact: [contactDtos, item.id] }"
                name="Primary contact"
                vid="PrimaryContact"
              >
                <b-form-checkbox
                  v-model="item.primaryContact"
                  :checked="item.primaryContact"
                  :state="errors.length > 0 ? false : null"
                  @change="onChange(index)"
                >
                  Primary contact
                </b-form-checkbox>
                <small class="text-danger">{{ errors[0] }}</small>
              </ValidationProvider>

`方法:

onChange(ref) {
      console.info(ref);
      for (let i = 0; i < this.contactDtos.length; i++) {
        console.info(`i == ${i}`);
        if (i !== ref) {
          this.$refs[`PrimaryContact${i}`][0].errors = [];
        }
      }
    },