【问题标题】:Getting a dynamic v-model to compare to data - VueJS and Vuelidate获取动态 v-model 以与数据进行比较 - VueJS 和 Vuelidate
【发布时间】:2020-08-15 02:48:22
【问题描述】:

我正在制作一个显示 3 个元素的简单表单

  1. 起始条码字段
  2. 结束条码字段
  3. 标签字段

用户在每个字段中输入 2 个条形码。 barcodeEnd 值的前 2 位与 allBarcodePrefixes 数据进行比较以查看是否匹配,如果不匹配,则打印相应的机构名称或“Agency Not Found”。如果没有匹配,表单会停在那里(用户必须修复条形码条目),但如果找到匹配项,它会弹出一个新行,其中包含一组新生成的字段和 v-models

在我使 v-models 动态化之前,这一切正常,因此我可以独立操作每个条目以进行验证和值

问题 发生了两件奇怪的事情,我需要伙计们的帮助。

  1. 当我模糊并进入下一个输入字段时,起始条形码字段会被清除。然后当我在那里输入一些东西时,它又回来了!我也有一个清晰的控制台,所以我不知道发生了什么。
  2. showAgencyName() 方法应该是获取 v-model 并将其与数据进行比较以获取代理名称。但是我的 v-model 是动态的,并且是字符串文字。我不知道如何提取这个值

我在codepen 中有代码供您查看并了解我的意思。我将onAddBarcodes 函数放在失败的行中,以便您可以看到它正确验证(该部分有效)。最终,该行将被删除,因为它只应在首先为机构验证后验证 minLength 和 maxLength。

    <div id="q-app">
        <div class="q-pa-md">
          <div>
            <div v-for="(barcode, index) in barcodes" :key="index">
              <div class="full-width row no-wrap justify-start items-center q-pt-lg">
                <div class="col-3">
                  <label>Starting Roll #:</label>
                  <q-input outlined square dense v-model="$v[`barcodeStart${index}`].$model"></q-input>

                  <div class="error-msg">
                    <div v-if="!$v[`barcodeStart${index}`].maxLength || !$v[`barcodeStart${index}`].minLength">
                      <span> Must be exactly 9 characters. </span>
                    </div>
                  </div>
                </div>

                <div class="col-3">
                  <label>Ending Roll #:</label>
                  <q-input outlined square dense v-model="$v[`barcodeEnd${index}`].$model" @change="showAgencyName(barcode)"></q-input>
                  <div class="error-msg">
                    <div v-if="!$v[`barcodeEnd${index}`].maxLength || !$v[`barcodeEnd${index}`].minLength">
                      <span> Must be exactly 9 characters. </span>
                    </div>
                  </div>
                </div>

                <div class="col-3">
                  <label>Agency:</label>
                  <div v-if="barcode.agencyName">
                    {{ barcode.agencyName }}
                  </div>
                  <div v-else></div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>


      Vue.use(window.vuelidate.default)
      const { required, minLength, maxLength } = window.validators

      new Vue({
        el: '#q-app',
        data () {
          return {
            barcodes: [
              {
                barcodeStart: "",
                barcodeEnd: "",
                agencyName: ""
              }
            ],
            newPackage: "",
            reset: true,
            allBarcodePrefixes: {
              "10": "Boston",
              "11": "New York",
              "13": "Houston",
              "14": "Connecticut",
              "16": "SIA",
              "17": "Colorado",
              "18": "Chicago"
            }
          }
        },
        validations() {
          const rules = {};
          this.barcodes.forEach((barcode, index) => {
            rules[`barcodeStart${index}`] = {
                minLength: minLength(9),
                maxLength: maxLength(9)
            };
          });

          this.barcodes.forEach((barcode, index) => {
            rules[`barcodeEnd${index}`] = {
                minLength: minLength(9),
                maxLength: maxLength(9)
            };
          });
          return rules;
        },
        methods: {
          onAddBarcodes() {
            // creating a new line when requested on blur of barcodeEnd
            const newBarcode = {
              barcodeStart: "",
              barcodeEnd: "",
              agencyName: ""
            };
            this.barcodes.push(newBarcode);
          },

          showAgencyName(barcode) {
            var str = barcode.barcodeEnd; // I need to pull the v-model value
            var res = str.substring(0, 2); //get first 2 char of v-model
            if (this.allBarcodePrefixes[res] == undefined) {
              //compare it to data
              barcode.agencyName = "Agency not found"; //pass this msg if not matched
              this.onAddBarcodes(); //adding it to the fail just for testing
            } else {
              barcode.agencyName = this.allBarcodePrefixes[res]; //pass this if matched
              this.onAddBarcodes(); //bring up a new line
            }
          },
        }
      })

提前致谢!

【问题讨论】:

    标签: javascript vue.js vuelidate


    【解决方案1】:

    您可以将 v-model 设置为 v-for 循环中的对象。让它看起来像这样。

    <q-input outlined square dense v-model="barcode.barcodeStart"></q-input>
    

    <q-input outlined square dense v-model="barcode.barcodeEnd"></q-input>
    

    这样他们会更新条形码对象,并且由于它是可观察的,您的 showAgencyName 函数可以保持原样,并且其中的条形码对象将被更新。

    编辑

    当您调用 onchange 事件时,您可以通过索引

    @change="showAgencyName(barcode, index)"
    

    然后在您的 showAgencyName 函数中,您可以使用 this.$v 访问验证。

    为确保规则已过期,您需要更新$model。像这样

     this.$v[`barcodeStart${index}`].$model = barcode.barcodeStart
    this.$v[`barcodeEnd${index}`].$model = barcode.barcodeEnd
    
    // Check for errors
    if (this.$v[`barcodeEnd${index}`].$error) {
       return
    }
    

    【讨论】:

    • 那么我无法验证它,它不会是动态的。这是传统的做法,也是我在最初设计中的做法。由于字段是动态生成的,因此它们必须具有其独特的动态生成的 v-model
    • 您可以继续执行上述操作,然后使用this.$v 访问您的showAgencyName 中的验证。然后在更改时,您也可以通过索引@change="showAgencyName(barcode, index)" 然后访问验证this.$v[`barcodeEnd${index}`]
    • 我会试试这个。为什么不做一个正确的答案,这样我就可以相信你了?
    • 你可以同时传入barcodeindex 然后在这一行var str = this.$v.barcode.barcodeEnd; 你不需要从中获取条形码。$v 只需使用var str = barcode.barcodeEnd
    • 没问题,我很高兴能帮上忙 :) 在验证方面,我认为问题之一是 vuelidate 似乎遇到问题的动态验证规则。我发现v-validate 很有帮助,可能是一个不错的选择
    猜你喜欢
    • 2019-11-01
    • 2019-12-27
    • 2018-06-13
    • 1970-01-01
    • 1970-01-01
    • 2021-04-25
    • 2020-06-08
    • 1970-01-01
    • 2018-11-04
    相关资源
    最近更新 更多