Проверьте все флажки vuejs

Я показываю список пользователей в таблице, каждая строка имеет флажок для выбора пользователя, а значение флажка - это идентификатор пользователя. Выбранные идентификаторы, в свою очередь, отображаются в диапазоне ниже таблицы.

Как я могу выбрать все флажки и снять все флажки с помощью флажка "Выбрать все", который у меня есть в заголовке моей таблицы? Я взаимодействую с DOM для этого или через объект vue, я думаю, что он должен быть последним, но совершенно неуверенным, как подойти к тому, что кажется легкой задачей?! Любая помощь будет оценена!

HTML

<div id="app">
    <h4>Users</h4>
    <div>
        <table>
            <tr>
                <th>Name</th>
                <th>Select <input type="checkbox" @click="selectAll"></th>
            </tr>
            <tr v-for="user in users">
                <td>{{ user.name }}</td>
                <td><input type="checkbox" v-model="selected" value="{{ user.id }}"></td>
            </tr>
        </table>
    </div>

    <span>Selected Ids: {{ selected| json }}</span>
</div>

Javascript/Vuejs

new Vue({
    el: '#app',
    data: {
        users: [ 
            { "id": "1", "name": "Shad Jast", "email": "[email protected]", 
            { "id": "2", "name": "Duane Metz", "email": "[email protected]"}, 
            { "id": "3", "name": "Myah Kris", "email": "[email protected]"}, 
            { "id": "4", "name": "Dr. Kamron Wunsch", "email": "[email protected]"}, 
            { "id": "5", "name": "Brendon Rogahn", "email": "[email protected]"}
        ],
        selected: []
    },
    methods: {
        selectAll: function() {
            // ?
        }
    }
})

Ответ 1

Добавление моего собственного ответа в качестве изменений в ответе nhydock не было принято (я думаю?).

Решение выбирает и выбирает все.

HTML

<div id="app">
    <h4>User</h4>
        <div>
            <table>
                <tr>
                    <th>Name</th>
                    <th>Select <input type="checkbox" @click="selectAll" v-model="allSelected"></th>
                </tr>
                <tr v-for="user in users">
                    <td>{{ user.name }}</td>
                    <td><input type="checkbox" v-model="userIds" value="{{ user.id }}"></td>
                </tr>
            </table>
        </div>

        <span>Selected Ids: {{ userIds | json }}</span>
</div>

Javascript/Vuejs

new Vue({
    el: '#app',
    data: {
        users: [ 
            { "id": "1", "name": "Shad Jast", "email": "[email protected]"}, 
            { "id": "2", "name": "Duane Metz", "email": "[email protected]"}, 
            { "id": "3", "name": "Myah Kris", "email": "[email protected]"}, 
            { "id": "4", "name": "Dr. Kamron Wunsch", "email": "[email protected]"}, 
            { "id": "5", "name": "Brendon Rogahn", "email": "[email protected]"}
        ],
        selected: [],
        allSelected: false,
        userIds: []
    },
    methods: {
        selectAll: function() {
            this.userIds = [];

            if (!this.allSelected) {
                for (user in this.users) {
                    this.userIds.push(this.users[user].id);
                }
            }
        },
    }
})

Рабочая скрипка: https://jsfiddle.net/okv0rgrk/3747/

Ответ 2

Я думаю, что ответ @Jeremy более чистый, но для свойства checked для каждого пользовательского объекта требуется значение, которое не имеет смысла, если данные поступают из запроса API.

Вот рабочий и чистый код для выбора/отмены всех строк без добавления свойства checked в объект пользователя:

new Vue({
    el: '#app',
    data: {
        users: [ 
            { "id": "1", "name": "Shad Jast", "email": "[email protected]" },
            { "id": "2", "name": "Duane Metz", "email": "[email protected]" }, 
            { "id": "3", "name": "Myah Kris", "email": "[email protected]" }, 
            { "id": "4", "name": "Dr. Kamron Wunsch", "email": "[email protected]" }
        ],
        selected: []
    },
    computed: {
        selectAll: {
            get: function () {
                return this.users ? this.selected.length == this.users.length : false;
            },
            set: function (value) {
                var selected = [];

                if (value) {
                    this.users.forEach(function (user) {
                        selected.push(user.id);
                    });
                }

                this.selected = selected;
            }
        }
    }
});
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>

<div id="app">
<h4>User</h4>
<div>
    <table>
        <tr>
            <th><input type="checkbox" v-model="selectAll"></th>
            <th align="left">Name</th>
        </tr>
        <tr v-for="user in users">
            <td>
                <input type="checkbox" v-model="selected" :value="user.id" number>
            </td>
            <td>{{ user.name }}</td>
        </tr>
    </table>
</div>
</div>

Ответ 3

Как насчет моего ответа, с меньшими свойствами, легко понять?

new Vue({
  el: '#app',
  data: {
    users: [{
      "id": "1",
      "name": "Shad Jast",
      "email": "[email protected]",
      'checked': false
    }, {
      "id": "2",
      "name": "Duane Metz",
      "email": "[email protected]",
      'checked': false
    }, {
      "id": "3",
      "name": "Myah Kris",
      "email": "[email protected]",
      'checked': false
    }, {
      "id": "4",
      "name": "Dr. Kamron Wunsch",
      "email": "[email protected]",
      'checked': false
    }, ],

  },
  computed: {
    selectAll: function() {
      return this.users.every(function(user){
        return user.checked;
      });
    }
  },
  methods: {
    toggleSelect: function() {
      var select = this.selectAll;
      this.users.forEach(function(user) {

        user.checked = !select;

      });
      this.selectAll = !select;
    },

  }
});
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>

<div id="app">
  <h4>User</h4>
  <div>
    <table>
      <tr>
        <th>Name</th>
        <th>Select
          <input type="checkbox" @click="toggleSelect" :checked="selectAll">
        </th>
      </tr>
      <tr v-for="user in users">
        <td>{{ user.name }}</td>
        <td>
          <input type="checkbox" v-model="user.checked">
        </td>
      </tr>
    </table>
  </div>

</div>

Ответ 4

Я хочу поблагодарить всех за то, что они поделились своими решениями. Это была большая помощь в обучении. Разработчик на gitter помог мне добавить флажок Default, который выберет подмножество массива с атрибутом "default", установленным в true.

вот код:

// based on https://jsfiddle.net/okv0rgrk/3747/

new Vue({
    el: '#app',
    data: {
        selected: [],
        defaultSelects: [],
        selectsArray: [ 

            {id: 'automotive', name: 'Automotive', class: 'industry', default: false},

            {id: 'beauty', name: 'Beauty', class: 'industry', default: true},

            {id: 'branding', name: 'Branding', class: 'industry', default: true},

            {id: 'btob', name: 'B to B', class: 'industry', default: false}
        ],
        selected: [],
    },
    computed: {
      defaultChecked: {
        get () {
          let defaults = this.selectsArray.filter(item => item.default).map(item => item.id)
          const hasAllItems = (baseArr, haystack) => haystack.every(item => baseArr.includes(item))
          const hasSameItems = (baseArr, haystack) => hasAllItems(baseArr, haystack) && hasAllItems(haystack, baseArr)
          return hasSameItems(this.selected, defaults)
        },
        set (value) {
          this.selected = []

          if (value) {
            this.selectsArray.forEach((select) => {
              if (select.default) {
                this.selected.push(select.id)
              }
            });
          }
        }
      }, // END defaultChecked
      selectAll: {
        get () {
          return this.selected.length === this.selectsArray.length
        },
        set (value) {
          this.selected = []

          if (value) {
            this.selectsArray.forEach((select) => {
              this.selected.push(select.id)
            })
          }
        }
      }, // END selectAll
    }
})
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>

<div id="app">
          
<div id="default-settings">

<label class="pref-button"><input type="checkbox" v-model="defaultChecked"><span>Default</span></label>

<label class="pref-button"><input type="checkbox" v-model="selectAll"><span>Select All</span></label>

</div>    
          
<label :for="select.id" v-for="select in selectsArray" v-bind:key="select.id"><input :value="select.id" v-model="selected" :id="select.id" :sector="select.id" :class="select.class" :default="select.default" type="checkbox">{{ select.name }}</label>

<span>Selected Ids: {{ selected }}</span>
  
</div>

Ответ 5

Все, что вам нужно сделать, это добавить своих пользователей, используя их идентификатор, так как вы ссылаетесь на их значения с помощью флажка и добавляете их в свой выбранный массив.

selectAll: function() {
    this.selected = [];
    for (user in this.users) {
        this.selected.push(this.users[user].id);
    }
}

Запуск JSFiddle

Ответ 6

Я думаю, что это может быть немного легче.

selectAll: function (isSelected) {
  if (!isSelected) {
    this.ids = []
    return false
  }
  if (isSelected) {
    this.rows.map(item => this.ids.push(item.id))
  }
}

Ответ 7

Часто нет необходимости отображать выбранные идентификаторы под таблицей. В таких случаях приведенный выше код можно упростить до:

HTML

<div id="app">
    <h4>Users</h4>
    <div>
        <table>
            <tr>
                <th>Name</th>
                <th>Select <input type="checkbox" v-model="selectAll"></th>
            </tr>
            <tr v-for="user in users">
                <td>{{ user.name }}</td>
                <td><input type="checkbox" :value="user.id" :checked="selectAll"></td>
            </tr>
        </table>
    </div>
</div>

VueJs

new Vue({
    el: '#app',
    data: {
        users: [ 
            { "id": "1", "name": "Shad Jast", "email": "[email protected]"}, 
            { "id": "2", "name": "Duane Metz", "email": "[email protected]"}, 
            { "id": "3", "name": "Myah Kris", "email": "[email protected]"}, 
            { "id": "4", "name": "Dr. Kamron Wunsch", "email": "[email protected]"}, 
            { "id": "5", "name": "Brendon Rogahn", "email": "[email protected]"}
        ],
        selectAll: false
    }
})

Ответ 8

У меня есть более простое решение, как указано ниже, и оно имеет все, что вы хотите. Реальные данные должны быть помещены в карту с индексированным именем в качестве метки флажка для будущего легкого доступа.

<template>
  <div align="left">
    <div>
      <input type="checkbox" id="all" :checked="allNamesSelected" @click="selectAll()">
      <label for="all">All</label>
    </div>
    <div v-for="(name) in names" :key="name">
      <input type="checkbox" :id="name" :value="name" :check="isChecked(name)" v-model="selectedNames">
      <label :for="name">{{name}}</label>
    </div>
  </div>
</template>

<script>
export default {
    data() {
        return {
            names: ['Automotive', 'Beauty', 'Branding', 'B to B'],
            selectedNames: [],
        }; 
    },
    computed: {
        allNamesSelected() {
            return this.names.length == this.selectedNames.length;
        },
    },
    methods: {
        selectAll() {
            if (this.allNamesSelected) {
                this.selectedNames = [];
            } else {
                this.selectedNames = this.names.slice();
            }
        },
        isChecked(name) {
            return this.selectedNames.includes(name);
        }
    }
}
</script>