【问题标题】:How can I validate date after / date before using VeeValidate v3 and vuejs-datepicker?如何在使用 VeeValidate v3 和 vuejs-datepicker 之前验证日期之后/日期?
【发布时间】:2019-09-03 15:53:49
【问题描述】:

如何使用 VeeValidate v3 和 VueJs-DatePicker 验证日期是否在某个日期之前或之后?

我正在使用: https://www.npmjs.com/package/vuejs-datepicker(最新) 和 https://baianat.github.io/vee-validate/(版本 3,不是 2)

VeeValidate 删除了它的日期验证功能,指出规则很脆弱、效果不佳等。

所以我假设我需要创建自定义规则,但我真的不知道从哪里开始并且可以使用帮助。

我使用 VueJS-DatePicker 包作为日期选择器,并且通过“格式”属性使用自定义格式。

我的日期选择器代码

<datepicker
    v-model="inputVal"
    :class="{ 'has-errors': !!errors[0] }"
    :placeholder="placeholder"
    calendar-button
    calendar-button-icon="fal fa-calendar-alt"
    bootstrapStyling
    :typeable="true"
    :disabled-dates="disabledDates"
    :format="customFormatter"
></datepicker>

使用 Moment 格式化日期

customFormatter(date) {
    return moment(date).format('MM/DD/YYYY');
},

【问题讨论】:

    标签: vue.js vee-validate vuejs-datepicker


    【解决方案1】:

    扩展@Barabas 的答案以具体包括 a) 在给定日期之前 b) momentJS 库 c) 严格的日期格式 'MM/DD/YYYY'

    import { extend } from "vee-validate";
    import * as moment from 'moment';
    
    const dateFormat = 'MM/DD/YYYY';
    
    extend("before", {
      params: ["limit", "included"],
      validate: (value, { limit, included }) => {
        limit = moment(limit, dateFormat);
        value = moment(value, dateFormat);
        return included 
          ? value.isSameOrBefore(limit)
          : value.isBefore(limit);
      },
      message: (fieldName, placeholders) => {
        let limit = moment(placeholders.limit).format(dateFormat);
        return `The ${fieldName} field must come before ${limit}`;
      }});
    }
    

    而且没有一刻(需要注意的是,在将字符串用于 Vue 数据属性或 limit 参数时,用户浏览器中的不同本地化设置可能会导致时髦 - 我强烈建议使用 'YYYY-MM-DD'使用字符串时的格式 - 当然,这不一定是向用户显示的内容)

    extend("before", {
      params: ["limit", "included", "displayTime"],
      validate: (value, { limit, included }) => {
        value = isNaN(value)
          ? Date.parse(value)
          : +value;
        limit = isNaN(limit)
          ? Date.parse(limit)
          : +limit;
        return included 
          ? value <= limit
          : value < limit;
      },
      message: (fieldName, placeholders) => {
        let limit = placeholders.limit instanceof Date
          ? placeholders.limit
          : new Date(placeholders.limit);
        limit = placeholders.displayTime
          ? limit.toLocaleString()
          : limit.toLocaleDateString();
        return `The ${fieldName} field must come before ${limit}`
      }});
    }
    

    【讨论】:

      【解决方案2】:
      1. 使用extend 创建您的自定义规则

      例如,这是我自己的自定义规则来检查集合中的项目是否足够:

      • 下面的value 是来自input 的值(不幸的是,vee-validate 仅适用于input
      • minrulesValidationProvider 属性中分号后的值
          extend('minAmountItems', {
              validate: (value, { min }) => {
                  return value >= min;
              },
              params: ['min'],
              message: '{_field_} should contains at least {min} items'
          });
      
      1. ValidationProvider包裹你datepicker

      比如我用ValidationProvider包裹了自己的组件:

      HTML

          <ValidationProvider
              ref="editableListProvider"
              tag="div"
              rules="minAmountItems:2"
              v-slot="{errors,invalid}"
              name="Collection"
          >
              <!-- LINE BELOW IS VERY IMPORTANT. -->
              <!-- THIS INPUT VALUE GOES TO VALIDATE FUNCTION OR CUSTOM RULE -->
              <input type="text" :value="items.length" disabled v-show="false" />
              <div class="column add-item-column">
                  <button @click="addItem">Add item</button>
              </div>
              <div class="column alert alert-danger" v-show="invalid">{{ errors[0] }}</div>
              <div class="column" v-for="(item, i) in items" :key="i">
                  <div class="row as-row row-no-padding">
                      <slot name="data" :data="{item, index: i}"></slot>
                      <div class="column column-clear">
                          <button class="button-outline button-icon" @click="removeItem(i)">
                              <i class="la la-close"></i>
                          </button>
                      </div>
                  </div>
              </div>
          </ValidationProvider>
      

      JS

              // another part of my component
      
              methods: {
                  addItem() {
                      this.$emit('editableList:itemAdded');
      
                      this.$nextTick(async () => {
                          // LINE BELOW IS IMPORTANT, BECAUSE AUTOMATIC VALIDATE WORKS 
                          // ONLY ONCHANGE EVENT OF INPUT
                          this.$refs.editableListProvider.validate();
                      });
                  },
                  removeItem(index) {
                      this.$emit('editableList:itemRemoved', { index });
      
                      this.$nextTick(async () => {
                          // LINE BELOW IS IMPORTANT, BECAUSE AUTOMATIC VALIDATE WORKS 
                          // ONLY ONCHANGE EVENT OF INPUT
                          this.$refs.editableListProvider.validate();
                      });
                  }
      
                  // other my methods
              }
      

      【讨论】:

      • 使用单独的隐藏&lt;input&gt; 是个好主意。这个解决方案最终对我有用,尽管由于渲染无限循环问题,我不得不将我的原始元素放在 &lt;ValidationProvider&gt; 之外。可能只是与vue-multiselect 冲突。如果你遇到这个问题,你可以给&lt;input&gt;标签添加一个“状态”绑定,并传入errorsvalid作为参数来调用自定义函数v-bind:state="getStateForValidation(errors, valid)"
      • 我确实需要做这样的事情来让验证为我正确触发:this.$nextTick(() =&gt; this.$refs.multiselectValidationProvider.validate(this.selectedItems.length)
      猜你喜欢
      • 2019-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-05
      • 2021-09-23
      • 2018-12-31
      相关资源
      最近更新 更多