【问题标题】:VueJS Master Checkbox Toggle with array valuesVueJS 主复选框切换数组值
【发布时间】:2018-08-06 11:47:54
【问题描述】:

我正在使用 VueJS,但在一系列复选框上实现两个功能时遇到问题。

  • 首先,我的复选框是动态构建的。
  • 我需要实现一个主“切换”复选框,单击该复选框时会选中或取消选中所有其他复选框。
  • 我需要在模型中保留一组选中项。

此脚本为我提供了切换复选框,但不填充“checkedNames”数组。我尝试在名称复选框中添加一个 v-model,但它只是检查了所有内容,但仍然没有填充数组。

new Vue({
  el: '#boxes',
  data: {
    checked: null,
    checkedNames: [],
    teams: [{
        name: 'team a',
        id: 'team-a',
        checked: null,
        members: [{
            'id': 1,
            'name': 'Dave'
          },
          {
            'id': 2,
            'name': 'Dee'
          },
          {
            'id': 3,
            'name': 'Dozy'
          },
          {
            'id': 4,
            'name': 'Beaky'
          },
          {
            'id': 5,
            'name': 'Mick'
          },
          {
            'id': 6,
            'name': 'Tich'
          }
        ]
      },
      {
        name: 'team b',
        id: 'team-b',
        checked: null,
        members: [{
            'id': 7,
            'name': 'John'
          },
          {
            'id': 8,
            'name': 'Paul'
          },
          {
            'id': 9,
            'name': 'George'
          },
          {
            'id': 10,
            'name': 'Ringo'
          }
        ]
      }
    ]
  }
});
<div id='boxes'>
  <ul>
    <li v-for="team in teams" style="width: 100px; float:left">
      <div>
        <input type="checkbox" class="form-check form-check-inline" v-bind:id="team.id" v-model="team.checked">
        <label v-bind:for="team.id"><strong>{{ team.name }}</strong></label>
      </div>
      <ul class="countries_list">
        <li v-for="member in team.members">
          <input type="checkbox" class="form-check form-check-inline" v-bind:id="member.id" v-bind.checked="{checked : team.checked}">
          <label v-bind:for="member.id">{{ member.name }}</label>
        </li>
      </ul>
    </li>
  </ul>
  <br>
  <span>Checked names: {{ checkedNames }}</span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

https://jsfiddle.net/50wL7mdz/133578/

有人能指出我正确的方向吗?

【问题讨论】:

  • 如果两个团队中都有Ringo 怎么办?
  • 这是可能的,但它会是一个不同的 Ringo。即,它将有一个唯一的 id。成员将​​始终只属于一个团队

标签: javascript html arrays vue.js


【解决方案1】:

我的看法:

1.为每个成员添加了'checked'属性。

2.将每个成员的复选框与每个成员的v-model="member.checked"绑定

3.为团队复选框绑定“更改”事件,如果单击,则为每个成员设置member.checked=team.checked

4. 将checkedNamed 转换为计算属性,使用for-loop 或reduce 打印出所有成员都已检查。

new Vue({
  el: '#boxes',
  computed: {
    computed_checkedNames: function() {
      let temp = '';
      for(teamIndex in this.teams) {
        temp += '[team=' + this.teams[teamIndex].name + ']{'
        for(memberIndex in this.teams[teamIndex].members) {
          temp += this.teams[teamIndex].members[memberIndex].checked ? this.teams[teamIndex].members[memberIndex].name + ',' : ''
        }
        temp += '},'
      }
      
      return temp
    }
  },
  data: {
    checked: null,
    //checkedNames: [],
    teams: [{
        name: 'team a',
        id: 'team-a',
        checked: false,
        members: [{
            'id': 1,
            'name': 'Dave',
            checked: false
          },
          {
            'id': 2,
            'name': 'Dee',
            checked: false
          },
          {
            'id': 3,
            'name': 'Dozy',
            checked: false
          },
          {
            'id': 4,
            'name': 'Beaky',
            checked: false
          },
          {
            'id': 5,
            'name': 'Mick',
            checked: false
          },
          {
            'id': 6,
            'name': 'Tich',
            checked: false
          }
        ]
      },
      {
        name: 'team b',
        id: 'team-b',
        checked: null,
        members: [{
            'id': 1,
            'name': 'John',
            checked: false
          },
          {
            'id': 2,
            'name': 'Paul',
            checked: false
          },
          {
            'id': 3,
            'name': 'George',
            checked: false
          },
          {
            'id': 4,
            'name': 'Ringo',
            checked: false
          },
          {
            'id': 6,
            'name': 'Tich',
            checked: false
          }
        ]
      }
    ]
  }
});
<div id='boxes'>
  <ul>
    <li v-for="team in teams" style="width: 100px; float:left">
      <div>
        <input type="checkbox" class="form-check form-check-inline" v-bind:id="team.id" v-model="team.checked" v-on:change="team.members.forEach(function(value, key){value.checked=team.checked});">
        <label v-bind:for="team.id"><strong>{{ team.name }}</strong></label>
      </div>
      <ul class="countries_list">
        <li v-for="member in team.members">
          <input type="checkbox" class="form-check form-check-inline" v-bind:id="member.id"  v-model="member.checked">
          <label v-bind:for="member.id">{{ member.name }}</label>
        </li>
      </ul>
    </li>
  </ul>
  <br>
  <span style="background-color:#8d9bb2">Checked names: {{ computed_checkedNames }}</span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

【讨论】:

  • 你如何处理价值观相同的团队?
  • @OnahOnallySunday 我更新了在team ateam b 中添加了一个元素={id: 6, name: 'Tich'} 的答案,看起来工作正常。
【解决方案2】:

这有点棘手。我认为您需要使用 @change 来控制所有内容,因为您有 checkAll 复选框功能。

在我这边,我不需要那些父 checked 属性,我只需要子选中属性来区分选中/未选中。基本上这是一个后备,因为您必须添加额外的属性checked

检查并尝试运行下面的sn-p。

new Vue({
        el : '#boxes',
        data : {
            teams: [
                {
                    name: 'team a',
                    id: 'team-a',
                    members: [
                        {'id': 1, 'name' : 'Dave', 'checked': false},
                        {'id': 2, 'name' : 'Dee', 'checked': false},
                        {'id': 3, 'name' : 'Dozy', 'checked': false},
                        {'id': 4, 'name' : 'Beaky', 'checked': true},
                        {'id': 5, 'name' : 'Mick', 'checked': false},
                        {'id': 6, 'name' : 'Tich', 'checked': false}
                    ]
                },
                {
                    name: 'team b',
                    id: 'team-b',
                    members: [
                        {'id': 7, 'name' : 'John', 'checked': false},
                        {'id': 8, 'name' : 'Paul', 'checked': false},
                        {'id': 9, 'name' : 'George', 'checked': false},
                        {'id': 10, 'name' : 'Ringo', 'checked': false},
                        {'id': 11, 'name' : 'Mick', 'checked': false}
                    ]
                }
            ]
        },
        computed: {
          getSelectedMembers: function() {
            var selectedMem = [];
            for(var teamIdx in this.teams) {
              var members = this.teams[teamIdx].members;
              for(var memberIdx in members) {
                if (members[memberIdx].checked) {
                  selectedMem.push(members[memberIdx].id);
                }
              }
            }
            return selectedMem;
          }
        },
        methods: {
          checkAll: function(idx, $event) {
            var member = this.teams[idx].members;
            for(var memberIdx in member) {
              member[memberIdx].checked = $event.target.checked;
            }
          }
        }
    });
.disp {
  display: inline-block;
}
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
<script src="https://unpkg.com/vue"></script>

<div id='boxes'>
    <ul>
        <li v-for="(team, index) in teams" style="width: 200px; float:left">
            <div>
                <input type="checkbox" class="form-check form-check-inline" v-bind:id="team.id" @change="checkAll(index, $event)" >
                <label v-bind:for="team.id"><strong>{{ team.name }}</strong></label>
            </div>
            <ul class="countries_list">
                <li v-for="member in team.members">
                    <input type="checkbox" class="form-check form-check-inline" v-bind:id="member.id" v-bind.checked="{checked : member.checked}" :value="member.name" @change="member.checked = !member.checked">
                    <label v-bind:for="member.id">{{ member.name }}</label>
                </li>
            </ul>
        </li>
    </ul>
    <div>getSelectedMembers: {{ getSelectedMembers }}</div>
    <br><br><br><br><br><br><br><br><br>
    <div class="disp" v-for="team in teams">
      <ul><strong>{{ team.id }}</strong>
        <li v-for="member in team.members" v-if="member.checked">{{member.name}}</li>
      </ul>
    </div>
    
</div>

【讨论】:

  • 谢谢@Dencio。首先,道歉。由于在我应该在床上的深夜问这个问题,我在我的脚本中打错了字。 id 值实际上应该是唯一的。我已经修改了我的问题。也就是说,您的解决方案非常接近。唯一的事情是我需要一个结果数组。这会为每个团队生成一个数组。这可以实现吗?
  • @Typhoon101 sup,你的意思是单个数组只用于names?它的id 怎么样?所以我可以尝试重现它。
  • 因为我只需要一个数组,是的,我想一组 id 将是唯一的方法。没事儿。谢谢
  • @Typhoon101 伙计,你介意这种阵列吗? selectedIds: [{teamId2: [memId1, memId2, memId3]},{teamId2: [memId1, memId2, memId3]}]
  • 最终,我需要一个仅包含选定项目的数组,例如:selectedId: [1,6,8,10,3]。但是数组是通过 Ajax 传递给一个 php 脚本的,所以如果需要的话,可能会有一些清理服务器端。
【解决方案3】:

首先,每个复选框都缺少value。添加它并将v-model 值分配给checkedNames 可以直接使用,但它当然不会全选。我在@change 上添加了一个新方法来解决这个问题,请参阅下面的小提琴:

https://jsfiddle.net/50wL7mdz/133688/

正如其他人指出的那样,这里的问题是您的 checkedNames 变量中没有唯一用户。将 user.name 更改为 user.id 不会解决此问题,因为您的 ID 只是索引(您有 1、2、3 等的重复项)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-15
    • 2013-07-12
    • 1970-01-01
    • 2017-07-07
    • 2012-07-03
    • 2021-10-10
    • 1970-01-01
    • 2020-03-03
    相关资源
    最近更新 更多