【问题标题】:Vuelidate $each: How can I validate a nested collection?Vuelidate $each:如何验证嵌套集合?
【发布时间】:2021-03-14 17:07:53
【问题描述】:

我很难掌握可能的基本概念。我正在传递一个location 作为道具。它有一个 json 列来存储additionalAttributes。它看起来像这样:

    "additionalProperties": [
        {
            "integrations": [
                {
                    "exampleVendor": {
                        "locationId": 123,
                        "positionId": 456
                    }
                }
            ]
        }
    ],
    "createdAt": "",
    "updatedAt": "",
    ...

以上是我硬编码到我的数据库 (Postgres) 中的内容,以尝试模拟数据返回时的样子。

我正在使用 vuelidate 文档的 validate collections 部分。

这是我用来尝试创建验证规则的内容:

validations: {
      location: {
        additionalProperties: {
          $each: {
            integrations: {
              $each: {
                exampleVendor: {
                  locationId: {required},
                  positionId: {required},
                }
              }
            }
          }
        }
      }
  },

在我的模板中,我尝试像这样连接验证:

<select id="my-id" 
    name="my-id" 
    class="py-3 px-3 mt-1 block w-full pl-3 pr-10 py-2 text-base sm:text-sm rounded-md" 
    v-if="locations"
    v-model.trim="$v.location.additionalProperties[0].integrations[0].exampleVendor.locationId.$model" 
    :class="[$v.location.additionalProperties[0].integrations[0].exampleVendor.locationId.$error ? 
    'focus:ring-red-500 focus:border-red-500 border-red-300' : 'focus:ring-gray-400 focus:border-gray-400 border-gray-300',]"
>
...
</select>

我已经使用这个组件有一段时间了,并且有一个很愚蠢的问题already asked

我也担心设置这么死板的路径additionalProperties[0].integrations[0]真的很糟糕。

我担心这个问题不会落后太多,但现在是时候寻求一些建议了。感谢您的任何建议!

编辑

@tony19 很好地解释了为什么只使用第一个值的数组。也许有更好的方法来做我正在做的事情;这是我的数据库中的数据可能的外观的更广泛视图。它现在除了集成之外还有其他属性。不过,目前我只专注于此。


"additionalProperties": [
        {
            "integrations": [
                {
                    "exampleVendor": {
                        "locationId": 123,
                        "positionId": 456
                    },
                    "anotherVendor": {
                        "foo": "abc",
                        "bar": "def"
                    },
                    "someOtherVendor": {
                        "thing": "value"
                    }
                }
            ],
            "anotherAttribute: {
                "one": "two"
            },
            "possibleAttributes": [...]
        }
    ],

【问题讨论】:

    标签: vue.js vuejs2 vuelidate


    【解决方案1】:

    正如您所说,additionalPropertiesintegrations 中可能有更多数组值,迭代这些属性比仅对第一个元素进行硬编码访问更有意义。

    Vuelidate docs for collections you linked 显示使用$each.$iter 迭代数组,所以我会为每个嵌套级别使用&lt;template v-for="ARRAY.$each.$iter"&gt;

    <template v-for="(addtlProperty, i) in $v.location.additionalProperties.$each.$iter">
      <template v-for="(integration, j) in addtlProperty.integrations.$each.$iter">
        <select
          :key="`${i}-${j}`"
          v-model.trim="integration.exampleVendor.locationId.$model"
          :class="[
            integration.exampleVendor.locationId.$error
              ? 'focus:ring-red-500 focus:border-red-500 border-red-300'
              : 'focus:ring-gray-400 focus:border-gray-400 border-gray-300',
          ]"
        >
        ...
        </select>
      </template>
    </template>
    

    demo

    【讨论】:

    • 哇!这太棒了。感谢您分享这个 - 正是我需要直截了当的推动。我希望有一种方法我也可以选择这个作为答案。
    【解决方案2】:

    在解决这个问题的过程中,我学到了很多东西。其中一个更重要的问题是如何解决 vuelidate 认为的问题。

    我创建了一个 change 处理程序来提供对 $model 值的洞察力。这是一个例子:

    <select @change="onChange"...">...</select>
    
    
    ...
    
    // start with what I know to be true.
    onChange() {
        console.log($v.location.additionalProperties);
    }
    
    

    使用上面的对象结构,然后我会移动到对象中,直到我最终得到这个:

    console.log($v.location.additionalProperties.$each[0].integrations.$each[0]. exampleVendor.locationId.$model; // 12345
    

    现在我有了模型的“路径”,我可以更新我的 &lt;select&gt; 元素:

    <select id="my-locationId" name="my-locationId" class="py-3 px-3 mt-1 block w-full pl-3 pr-10 py-2 text-base sm:text-sm rounded-md" 
        v-model.trim="$v.location.additionalProperties.$each[0].integrations .$each[0].exampleVendor.locationId.$model"
        :class="[
                 $v.location.additionalProperties.$each[0].integrations.$each[0].exampleVendor.locationId.$error
                            ? 'focus:ring-red-500 focus:border-red-500 border-red-300'
                            : 'focus:ring-gray-400 focus:border-gray-400 border-gray-300',
                        ]"
        >
        <option selected="selected" value="">Select</option>
        <option
            v-for="location in myLocations"
            :key="location.id"
            :value="location.id"
        >
            {{ location.name }}
        </option>
    </select>
    

    现在嵌套路径正在收集/设置数据,我可以设置验证规则:

    ...
    
    data: () => ({...}),
    
    validations: {
      location: {
          additionalProperties: {
            $each: {
              integrations: {
                $each: {
                  exampleVendor: {
                    locationId: { required },
                    positionId: { required },
                  },
                },
              },
            },
         },
      },
    },
    
    ...
    
    methods: {
      async save() {
          this.$v.$touch();
    
          if (this.$v.$invalid) {
            this.errors = true;
          } else {
            try {
              const params = {
                location: this.location, // location is passed in as props
                method: this.location.id ? "PATCH" : "POST",
              };
    
              console.log('params: ', params);  // {...}
    
              // Save to vuex or ??
            } catch (error) {
              console.log('there was an error:', error);
            }
          }
        },
    }
    

    希望这对其他人有所帮助 - 这不是非常直接的,我确信有更有效的方法,但这最终对我有用。

    编辑 2

    请务必遵循@tony19 的建议答案。提供的解决方案消除了我在问题中所说的“僵化”。

    【讨论】:

    • 如果只访问第一个元素,为什么还需要数组?
    • 好问题!也许有更直接的方法。我在我的问题中添加了一个 EDIT,以显示 additionalProperties 最终的外观以及为什么我觉得我需要数组。我很高兴听到你的想法!
    • 和你的问题一样,我真的不喜欢这个:$v.location.additionalProperties.$each[0].integrations.$each[0].exampleVendor. 看起来很死板。我更愿意:$v.location.additionalProperties.integrations.$each.exampleVendor.foo... 鉴于 additionalProperties 是一个数组(或者这可能是问题所在——它不需要它 IDK)
    猜你喜欢
    • 2018-07-25
    • 2016-03-15
    • 1970-01-01
    • 2012-11-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2021-08-03
    相关资源
    最近更新 更多