@EVOSandru6

Как во Vue сделать 2 кнопки переключателя Да и Нет чекбокса с v-model?

Добрый день,

Посредственный вариант с <label: for="id-of_checkbox"> не подходит, т.к. каждая из 2 кнопок является именно переключателем с Да на Нет и обратно

Данные чекбоксы идут в цикле v-for. Привожу вариант, где пробовал использовать чистый JS для прокликивания кнопок:

<div class="form-group" v-for="attribute in attributes">
            <input :id="getInputId(attribute)"
                   type="checkbox"
                   v-model="definedAttributes[makeKey(attribute)]"/>

            <button class="btn btn-primary" @click="checkBoxYes(attribute)">Да</button>
            <button class="btn btn-primary" @click="checkBoxNo(attribute)">Нет</button>
        </div>


export default {
        ...
       data() {
            return {
                attributes: [], // наполняется посредством rest API
                definedAttributes: {}, // формируется за счет прокликивания чекбоксов
            }
        },
           methods: {
                checkBoxYes(attribute) {
                // некое условие

                let selector = this.getInputId(attribute);

                // выводится правильный id чекбокса как в разметке (как формируется - неважно)
                console.log('selector', selector); 

                 // гаолчка ставится только визуально, объяект definedAttributes не переопределяется, реактивности нет
                document.getElementById(selector).checked = true;
            },
            checkBoxNo(attribute) {
                    // аналогично
            },
     }
}


Также пробовал через Object.assign переопределить объект в методе checkBoxYes:

this.definedAttributes = Object.assign(this.definedAttributes, {[computedKey]: true});
                // В консоли изменения видны, но реактивности нет
                console.log('this.definedAttributes', this.definedAttributes)


Реактивность работает только вслучае, если мышкой кликать по галочкам.

Подскажите пожалуйста способ - связать реактивно 2 кнопки (true и false) и чекбокс?

Чекбокс (v-model каждого элемента итерации) в последствии отображаться недолжен, только ДА и НЕТ)

PS

Но странное дело, при клике по кнопке ДА ничего реактивно и визуально не происходит, но если я кликаю на чекбокс другой итерации, то в объекте оказываются все ключи со значениями, инициированные ранее прокликиваниями по кнопкам.

Может есть какой-то способ насильной синхронизации реактивности?

this.$nextTick(); не помог
  • Вопрос задан
  • 361 просмотр
Решения вопроса 2
0xD34F
@0xD34F Куратор тега Vue.js
attributes: [], // наполняется посредством rest API

Вот такого не надо. Какая разница, откуда берутся данные? Компоненту об этом знать не надо. Пусть компонент получает массив атрибутов в виде параметра: props: [ 'value' ]; а при необходимости его обновить отдаёт наверх новый массив: this.$emit('input', this.value.map(...)). Это позволит использовать на компоненте директиву v-model: <attributes-list v-model="attributes" />.

document.getElementById(selector).checked = true;

И такого не надо. Манипулировать следует только и исключительно данными. Сделайте метод, который будет получать объект атрибута и новое значение, собирать новый массив данных и дёргать $emit:

methods: {
  update(attr, checked) {
    this.$emit('input', this.value.map(n => n === attr
      ? { ...n, checked }
      : n
    ));
  },
},

<div v-for="n in value">
  <input type="checkbox" :checked="n.checked" @input="update(n, $event.target.checked)">
  <button @click="update(n, true)">Да</button>
  <button @click="update(n, false)">Нет</button>
</div>

Если хотите по прежнему использовать v-model на чекбоксах, то можно собрать объект вида { 'имя/id/ещё что-то уникальное': checked } и завернуть его в Proxy:

computed: {
  attributes() {
    return new Proxy(Object.fromEntries(this.value.map(n => [ n.name, n.checked ])), {
      set: (target, key, val) => {
        this.$emit('input', this.value.map(n => n.name === key
          ? { ...n, checked: val }
          : n
        ));
        return true;
      },
    });
  },
},

<div v-for="(v, k) in attributes">
  <input type="checkbox" v-model="attributes[k]">
  <button @click="attributes[k] = true">Да</button>
  <button @click="attributes[k] = false">Нет</button>
</div>
Ответ написан
@EVOSandru6 Автор вопроса
Решил так:

checkBoxToggle(attribute, bool) {
                let key = this.makeKey(attribute);

                if(this.definedAttributes[key] !== undefined) {
                    this.definedAttributes[key] = bool;
                } else {
                    this.definedAttributes = Object.assign({}, this.definedAttributes, {[key]: bool});
                }
            },
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы