VueJS 主复选框切换数组值

Posted

技术标签:

【中文标题】VueJS 主复选框切换数组值【英文标题】:VueJS Master Checkbox Toggle with array values 【发布时间】: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。成员将​​始终只属于一个团队 【参考方案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 等的重复项)。

【讨论】:

以上是关于VueJS 主复选框切换数组值的主要内容,如果未能解决你的问题,请参考以下文章

如何添加数组VueJS?

在 VueJS 中如何将输入类型复选框与输入类型文本相关联

未选中时,具有对象作为绑定到数组属性的值的 VueJS 复选框不会脱离数组

在Vue js中将复选框选择的值分组到数组中

处理VueJS中的复选框

父更新时VUE Js子不更新