首页 文章

vuejs将复选框数组传递给父模板只传递一个值

提问于
浏览
0

我看了这个潜在的骗局,比如这个one并不一定能解决我的问题 .

我的情况是我有一个带有标签和组件的组件附加到v模型 . 该组件将与其他表单组件结合使用 . 目前,它可以工作 - 但它只会将一个值传回给父级,即使单击这两个复选框也是如此 .

Form page:

<template>
  <section>
    <h1>Hello</h1>
    <list-orgs v-model="selectedOrgs"></list-orgs>
    <button type="submit" v-on:click="submit">Submit</button>
  </section>
</template>

<script>
// eslint-disable-next-line
import Database from '@/database.js'
import ListOrgs from '@/components/controls/list-orgs'

export default {
  name: 'CreateDb',
  data: function () {
    return {
      selectedOrgs: []
    }
  },
  components: {
    'list-orgs': ListOrgs,
  },
  methods: {
    submit: function () {
      console.log(this.$data)
    }
  }
}
</script>

Select Orgs Component

<template>
  <ul>
    <li v-for="org in orgs" :key="org.id">
      <input type="checkbox" :value="org.id" name="selectedOrgs[]" v-on:input="$emit('input', $event.target.value)"  />
      {{org.name}}
    </li>
  </ul>
</template>

<script>
import {db} from '@/database'

export default {
  name: 'ListOrgs',
  data: () => {
    return {
      orgs: []
    }
  },
  methods: {
    populateOrgs: async function (vueObj) {
      await db.orgs.toCollection().toArray(function (orgs) {
        orgs.forEach(org => {
          vueObj.$data.orgs.push(org)
        })
      })
    }
  },
  mounted () {
    this.populateOrgs(this)
  }
}
</script>

目前,数据库中有两个伪造的组织ID为1和2.在单击两个复选框并单击提交按钮时,selectedOrgs数组仅包含2,就好像第二次单击实际上覆盖了第一个 . 我通过只检查一个框并点击提交验证了这一点,并且传递了1或2的值 . 似乎数组方法在组件级别工作,但在组件级别上不工作 .

任何帮助表示赞赏 .

UPDATE

感谢puelo的评论我切换了我的orgListing组件以发出连接到v模型的数组,如下所示:

export default {
  name: 'ListOrgs',
  data: () => {
    return {
      orgs: [],
      selectedOrgs: []
    }
  },
  methods: {
    populateOrgs: async function (vueObj) {
      await db.orgs.toCollection().toArray(function (orgs) {
        orgs.forEach(org => {
          vueObj.$data.orgs.push(org)
        })
      })
    },
    updateOrgs: function () {
      this.$emit('updateOrgs', this.$data.selectedOrgs)
    }
  },
  mounted () {
    this.populateOrgs(this)
  }
}

然后在另一端我只是console.log()返回 . 这“有效”,但有一个缺点,似乎$ emit在更新selectedOrgs的值之前被触发,所以它总是一个“检查” . 实际上,我希望emit等待$ data对象更新,这可能吗?

2 回答

  • 1

    表单绑定中 v-model 的文档仍适用于自定义组件,如:

    v-model本质上是用于更新用户输入事件数据的语法糖...

    https://vuejs.org/v2/guide/forms.html#Basic-Usagehttps://vuejs.org/v2/guide/components-custom-events.html#Customizing-Component-v-model

    所以在你的代码中

    <list-orgs v-model="selectedOrgs"></list-orgs>
    

    被翻译成:

    <list-orgs :value="selectedOrgs" @input="selectedOrgs = $event.target.value"></list-orgs>
    

    这意味着 v-on:input="$emit('input', $event.target.value) 内部的每个发射实际上只用一个值覆盖数组:复选框的状态 .

    编辑以解决评论:

    也许根本不使用 v-model 只听一个像 @orgSelectionChange="onOrgSelectionChanged" 这样的事件 .

    然后,您可以使用复选框的状态和组织的ID发出一个对象(以防止重复):

    v-on:input="$emit('orgSelectionChanged', {id: org.id, state: $event.target.value})"

    最后,另一端的方法检查重复:

    onOrgSelectionChanged: function (orgState) {
        const index = selectedOrgs.findIndex((org) => { return org.id === orgState.id })
        if (index >= 0) selectedOrgs.splice(index, 1, orgState)
        else selectedOrgs.push(orgState)
    }
    

    这是非常基本的,未经过测试,但应该让您了解如何解决这个问题 .

  • 0

    非常感谢@puelo的帮助,它帮助澄清了一些事情,但并不一定能解决我的问题 . 正如我想要的那样,在填充数组的复选框上的 v-model 的简单性,然后在保持封装的同时将其传递给父级 .

    所以,我做了一个小改动:

    Select Orgs Component

    <template>
      <ul>
        <li v-for="org in orgs" :key="org.id">
          <input type="checkbox" :value="org.id" v-model="selectedOrgs" name="selectedOrgs[]" v-on:change="updateOrgs"  />
          {{org.name}}
        </li>
      </ul>
    </template>
    
    <script>
    import {db} from '@/database'
    
    export default {
      name: 'ListOrgs',
      data: () => {
        return {
          orgs: []
        }
      },
      methods: {
        populateOrgs: async function (vueObj) {
          await db.orgs.toCollection().toArray(function (orgs) {
            orgs.forEach(org => {
              vueObj.$data.orgs.push(org)
            })
          })
        },
        updateOrgs: function () {
          this.$emit('updateOrgs', this.$data.selectedOrgs)
        }
      },
      mounted () {
        this.populateOrgs(this)
      }
    }
    </script>
    

    Form Page

    <template>
      <section>
        <h1>Hello</h1>
        <list-orgs v-model="selectedOrgs" v-on:updateOrgs="updateSelectedOrgs"></list-orgs>
        <button type="submit" v-on:click="submit">Submit</button>
      </section>
    </template>
    
    <script>
    // eslint-disable-next-line
    import Database from '@/database.js'
    import ListOrgs from '@/components/controls/list-orgs'
    
    export default {
      name: 'CreateDb',
      data: function () {
        return {
          selectedOrgs: []
        }
      },
      components: {
        'list-orgs': ListOrgs
      },
      methods: {
        updateSelectedOrgs: function (org) {
          console.log(org)
        },
        submit: function () {
          console.log(this.$data)
        }
      }
    }
    </script>
    

    这里的主要变化是,我现在在单击复选框时触发 updateOrgs 的方法,并通过此方式传递整个 selectedOrgs 数组 . $ emit('updateOrgs',this . $ data.selectedOrgs)`

    这利用了v模型维护它们是否被检查的数组 . 然后在表单页面上,我只使用 v-on:updateOrgs="updateSelectedOrgs" 在组件上侦听此事件,该事件包含已填充的数组并保持封装 .

相关问题