引导验证冲突

时间:2020-06-15 19:30:29

标签: javascript twitter-bootstrap vue.js bootstrap-4 vue-cli

我正在使用Vue.js和Bootstrap设计网站。我有一个要在其上运行自定义验证的表单。直到用户单击“提交”为止,该方法都可以正常工作,这会根据引导文档将application/octet-stream类添加到表单中。

这时,任何需要输入的字段(无论是否满足我的自定义验证要求)都会被标记为有效,并带有绿色边框和复选标记。我的自定义验证仍在运行,并且正确显示was-validated。但是,似乎b-form-invalid-feedback会将具有所需道具的字段标记为有效,而未考虑我的自定义验证,这会导致验证冲突,因为字段具有绿色的复选标记(因为它满足必需的属性),但是仍然是错误消息,因为根据我的自定义验证它尚未生效。

我尝试删除was-validated样式,但这并不是我想要的效果,因为我确实希望它在每次验证均有效时显示这些样式。希望如果没有,我会提供图片。我还有第二个问题,我有一个日期选择器,即使添加了:valid也根本不显示b-form-invalid-feedback

我的代码

was-validated
<b-form @submit.prevent="addReview" name="review-form" novalidate>
  <div class="name">
    <label class="sr-only" for="form-input-name">Name</label>
    <b-input id="form-input-name" class="form-inputs mb-2 mr-sm-2 mb-sm-0" v-model="name" placeholder="Name" required :state="isStateValid(this.name)"></b-input>
    <b-form-invalid-feedback id="form-input-name">
      You must enter a name
    </b-form-invalid-feedback>
  </div>

  <div class="date">
    <label class="sr-only" for="example-datepicker">Choose a date</label>
    <b-form-datepicker id="datepicker" v-model="dateVisited" class="mb-2" required placeholder="Date Visited" :state="isStateValid(this.dateVisited)"></b-form-datepicker>
    <b-form-invalid-feedback id="datepicker">
      You must enter a valid date
    </b-form-invalid-feedback>
  </div>

  <div class="service">
    <label class="sr-only" for="form-input-service">Service Provided</label>
    <b-input id="form-input-service" class="form-inputs mb-2" placeholder="Service Provided" v-model="service" required :state="isStateValid(this.service)"></b-input>
    <b-form-invalid-feedback id="form-input-service">
      You must enter the service provided
    </b-form-invalid-feedback>
  </div>

  <div class="email">
    <label class="sr-only" for="inline-form-input-username">Email</label>
    <b-input id="inline-form-input-username" class="form-control mb-2 mr-sm-2 mb-sm-0" placeholder="Email" v-model="email" required :state="emailStateValidation"></b-input>
    <b-form-invalid-feedback id="inline-form-input-username">
      You must enter the part of your email that comes before the '@' symbol
    </b-form-invalid-feedback>
  </div>

  <div class="domain">
    <label class="sr-only" for="inline-form-input-domain">Domain</label>
    <b-input-group prepend="@" class="mb-2 mr-sm-2 mb-sm-0">
      <b-input id="inline-form-input-domain" placeholder="Domain ex: gmail.com" v-model="domain" required :state="domainStateValidation"></b-input>
      <b-form-invalid-feedback id="inline-form-input-domain">
        You must enter the part of your email that comes after the '@' symbol
      </b-form-invalid-feedback>
    </b-input-group>
  </div>

  <div class="description">
    <label class="sr-only" for="textarea-rows">Describe Your Experience</label>
    <b-form-textarea class="mb-3 mr-sm-2 mb-sm-0" id="textarea-rows" placeholder="Describe Your Experience" rows="4" required v-model="description" :state="isStateValid(this.description)"></b-form-textarea>
    <b-form-invalid-feedback id="textarea-rows">
      You must enter a description of your experience
    </b-form-invalid-feedback>
  </div>

  <b-button type="submit">Save</b-button>
</b-form>

问题

  1. 解决所需验证与我的自定义验证之间的冲突 导致输入字段过早地标记为有效
  2. 如果提交,则在表单提交的日期选择器上显示computed: { emailStateValidation() { if (this.email) { return this.emailIsValid() ? true : false; } return null; }, domainStateValidation() { if (this.domain) { return this.domainIsValid() ? true : false; } return null; }, }, methods: { emailIsValid() { let regEx = /^(?!.*@)((^[^\.])[a-z0-9\.!#$%&'*+\-\/=?^_`{|}~"]*)*([^\.]$)/; return regEx.test(this.email); }, domainIsValid() { let regEx = /((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return regEx.test(this.domain); }, isStateValid(variable) { if (variable) { return variable.length > 0 ? true : false; } return null; }, addReview() { let mainForm = document.getElementsByName("review-form")[0]; mainForm.classList.add("was-validated"); ... 未选择日期

2 个答案:

答案 0 :(得分:1)

  1. 根本上,was-validated不是引导程序本机的,它是浏览器本机的,它也不了解:state。如果要使用was-validated,则不能使用自定义验证。如果要使用自定义验证。请参阅建议2。基本上,使用另一个变量来控制是否应应用验证。

  2. 来自bootstrap-vue的文档

设置后,在组件上添加aria-required="true"属性。所需的验证需要由您的应用程序处理

您需要显式检查验证是否应显示,文档中尚不清楚required的实际作用,但它不会影响验证。这就解释了为什么该部分不起作用。我个人在提交时设置了一个全局this.showValidations = true,以便验证实际上在正确的时间运行,而不是在预期的时间(之前和之后)运行。对于您的情况,可以检查要显式添加的was-validated类。这不是很好,但似乎必须在这里完成。

答案 1 :(得分:1)

简而言之,从您的Vue模板中的novalidate中删除<form>。设置novalidate时,输入将在其整个生命周期内保持其:valid状态,直到您显式调用setCustomValidity为止。 Working Sandbox

由于Bootstrap样式也适用于:valid:invalid状态,因此,即使您的自定义验证器确定输入无效,也将同时应用有效样式和无效样式,即:valid.is-invalid,但我想只是这样,:valid样式优先于当前编写Bootstrap样式表的方式。

使用̶̶n̶o̶v̶a̶l̶i̶d̶a̶t̶e̶̶当̶y̶o̶u̶'̶r̶e̶实施完整验证解决方案包括自己̶̶r̶e̶q̶u̶i̶r̶e̶d̶̶̶v̶a̶l̶i̶d̶a̶t̶o̶r̶.̶

借助Bootstrap,由于它还将样式应用于输入的:valid:invalid状态,因此最好不要使用novalidate

当然,这将使浏览器弹出窗口要求填写某些可能不需要的字段。

建议:在表单上使用validated属性并将其绑定到表单的状态,并在true中将其设置为addReview(),它将自动添加{ {1}}类,您无需直接操作DOM。

编辑:由于删除was-validated会启用浏览器验证,因此不会在表单上触发novalidate事件,因此,submit类不会添加到表单中。这在我的原始答案中提出了一个问题,因为没有was-validated时不会显示消息和图标。我已经修改了沙箱,以提供针对此问题的解决方案,该解决方案是将was-validated事件绑定到提交按钮以进行验证逻辑,并使用click事件来完成成功验证后应该发生的事情。

日期选择器的编辑:日期选择器从未失效的原因是由于submit方法中的问题,尤其是以下部分:

isStateValid()

由于if(variable) { // "" evaluates to false // ... } 的计算结果为false,因此它将始终返回""。该问题的解决方法是与上述建议结合使用,以维护表单的null状态。现在,我们不检查validated,而是检查if(variable),如果它是if(this.validated),我们只需检查长度并返回truetrue