Vue.js Vuelidate$each:如何验证嵌套集合?

Vue.js Vuelidate$each:如何验证嵌套集合?,vue.js,vuejs2,vuelidate,Vue.js,Vuejs2,Vuelidate,我真的很难理解可能的基本概念。我将一个位置作为道具传入。它有一个json列来存储附加属性。它看起来像这样: "additionalProperties": [ { "integrations": [ { "exampleVendor": { "locationI

我真的很难理解可能的基本概念。我将一个
位置作为道具传入。它有一个json列来存储
附加属性
。它看起来像这样:

    "additionalProperties": [
        {
            "integrations": [
                {
                    "exampleVendor": {
                        "locationId": 123,
                        "positionId": 456
                    }
                }
            ]
        }
    ],
    "createdAt": "",
    "updatedAt": "",
    ...
<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>
以上是我硬编码到数据库(Postgres)中的内容,试图模拟数据返回时的样子

我从vuelidate文档的一部分开始工作

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

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

在我的模板中,我尝试连接验证,如下所示:

    "additionalProperties": [
        {
            "integrations": [
                {
                    "exampleVendor": {
                        "locationId": 123,
                        "positionId": 456
                    }
                }
            ]
        }
    ],
    "createdAt": "",
    "updatedAt": "",
    ...
<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>

通过这项工作,我学到了很多东西。其中一个更重要的问题是如何排除vuelidate所认为的问题

我创建了一个
change
处理程序,以便深入了解
$model
值是什么。以下是一个例子:

<select @change="onChange"...">...</select>


...

// start with what I know to be true.
onChange() {
    console.log($v.location.additionalProperties);
}

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

<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>
希望这对其他人有所帮助-这并不是非常直接&我相信有一种更有效的方法,但这最终对我有效

编辑2


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

正如您所评论的,在
附加属性和
集成中可能有更多的数组值,迭代这些属性比只硬编码访问第一个元素更有意义

图中显示了使用
$each.$iter
迭代数组,因此我将对每个嵌套级别使用


...

如果只想访问第一个元素,为什么需要阵列?好问题!也许有更直接的方法。我在问题中添加了一个编辑,以显示
additionalProperties
的最终外观,以及我觉得需要数组的原因。我很想听听你的想法!和你的问题一样,我真的不喜欢这样:
$v.location.additionalProperties.$each[0]。integrations.$each[0]。exampleVendor.
它看起来很僵硬。我更愿意:
$v.location.additionalProperties.integrations.$each.exampleVendor.foo…
考虑到
additionalProperties
是一个数组(或者可能这就是问题所在——它不需要IDK)哇!这太棒了。谢谢你分享这一点-这正是我需要的推动,以得到正确的设置。我希望有一种方法我也能选择这个作为答案。
...

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);
        }
      }
    },
}