One way for you to solve your problem is to treat the "No alternative" option as a special option. That is, it will not be included in data.options
or data.checkeds
because it has a special behavior.
The basic idea is to have:
- A array of _strings with the options (which is already yours
prop
that you call options
)
- A array of boolean values of the same size as the checkbox of its component.
- One computed Property which will return the checkbox status "No alternative". That is, it will be true only if all the checkboxes are unchecked.
- A method to "zero" the checkboxes, that is, a method that you will assign
false
for all values of the array that stores the states of the checkboxes (item 2 of this list).
Basically what I do is guard the states (checked
) in a array separate and have a method that assigns false
for these states. A computed Property serves only as a feedback visual for the user, that is, if no alternative is checked, the option "No option" will be checked
, otherwise it will be unchecked.
That said, the following code does exactly what the above list suggests. The only difference is that I run the method that "Zera" the checkboxes when starting the component, so data.checked
is started with the same number of elements from data.options
.
Code
new Vue({
el: '#app',
data: () => ({
// Este array será dinâmico no componente pois será um prop
options: ['Opção A', 'Opção B', 'Opção C'],
// Deve ser iniciado com o mesmo tamanho de `options`
checked: [],
}),
methods: {
// Cria um array com N elementos de valor "false"
resetChecked() {
this.checked = Array(this.options.length).fill(false);
}
},
computed: {
// É true apenas se todos elementos de `checked` forem `false`
nenhumaOpcao() {
return this.checked.every(c => !c)
}
},
// Inicia a variável `checked` ao montar o componente
mounted() {
this.resetChecked();
}
})
.label { display: block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h3>Opções</h3>
<!-- Opções dinâmicas do componente -->
<label v-for="(option, i) in options" class="label">
<input type="checkbox" :checked="checked[i]" v-model="checked[i]">
{{ option }}
</label>
<!-- Opção fixa "Nenhuma opção" -->
<label>
<input type="checkbox" :checked="nenhumaOpcao" @click="resetChecked">
Nenhuma opção
</label>
</div>
Extra
resetChecked() {
// Cria um array com N elementos de valor "false"
this.checked = Array(this.options.length).fill(false);
}
In the above code I create a method to "zero" the _array _ checked
using the constructor of Array and the method Array.fill
.
The array builder, when you take an integer as argument, create an empty array of size N. Example:
let a = Array(3);
a[0]; // undefined
a[2]; // undefined
a[100]; // undefined
a.length; // 3
While Array.fill
fills an array with the received value. I use this method along with the above method to create an array with N values false
to use in the component.
Array(5).fill(false); // [false, false, false, false, false]
Array(3).fill(0); // [0, 0, 0]
If compatibility is a problem you can use any other method to create an array. Example:
function createArray(size, initial_value) {
let new_array = [],
i=0;
for ( ; i < size ; i++) new_array.append(initial_value);
return new_array;
}
nenhumaOpcao() {
// É true apenas se todos elementos de `checked` forem false
return this.checked.every(c => !c)
}
In the above code I use the method Array.every
to test whether all elements of checked
sane false
. It is unlikely that you have problems from compatibility with this method, but for study purposes you could use something like:
function every(array, funcao) {
for (let i=0, l=array.length ; i<l ; i++) {
if (!funcao(array[i])) return false;
}
return true;
}
Igor, you want a checkbox behave like radio button? Wouldn’t it be easier for you to use radio?
– fernandosavio
I also thought about it, but by the requirement of the project the user can mark 2 options, so the radio does not serve. is like: problem1, problem2, uninformed problem, he may have had the 2 problems
– Igor Oliveira
I got it wrong Igor, I’m sorry. I’ll think of something to help you.
– fernandosavio