there is this page with several cards and each card has its own status radio buttons: ok, missing, error.
I wanna change the status of each card without changing others. So I created a method to change the class on @change event, but as all cards bind the same ‘data’, like ‘status’, changing one, changing all.
Lets see some code
<input class=”form-check-input” type=”radio” name=”dadosCadastrais” id=”inlineRadio1” value=”option1” @change=”ok”>
<input class=”form-check-input” type=”radio” name=”dadosCadastrais” id=”inlineRadio2” value=”option2” @change=”falta”>
<input class=”form-check-input” type=”radio” name=”dadosCadastrais” id=”inlineRadio3” value=”option3” @change=”erro”>
The script part:
var vue.js = new Vue({
el: ‘#app’,
data: {
status: ‘’
}
And the method() part:
ok() {
this.status = ‘bg-primary text-white’},
//will code some AJAX too
falta() {
this.status = ‘bg-warning text-black’},
//will code some AJAX too
erro() {
this.status = ‘bg-danger text-white’
//will code some AJAX too
}
The hole card deck code is:
<div class=”card-columns”>
<div class=”card” :class=”status”>
<div class=”card-body”>
<h5 class=”card-title”>Dados Cadastrais</h5>
<p class=”card-text”>
LOGRADOURO: @{ rua }, </p><p> NMERO: @{ numero }, </p><p> BAIRRO: @{ bairro }, </p><p> TEMPO DE RESIDNCIA: @{ tempoResidencia
}, </p><p> CIDADE: @{ cidade }, </p><p> UF: @{ uf }, </p><p> TELEFONE: @{ telefone }, </p><p> CELULAR: @{ celular }, </p><p> CEP:
@{ CEP }
</p>
</div>
<div class=”card-footer text-muted”>
<div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosCadastrais” id=”inlineRadio1” value=”option1” @change=”ok”> <label class=”form-check-label” for=”inlineRadio1”>OK</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosCadastrais” id=”inlineRadio2” value=”option2” @change=”falta”> <label class=”form-check-label” for=”inlineRadio2”>Falta</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosCadastrais” id=”inlineRadio3” value=”option3” @change=”erro”> <label class=”form-check-label” for=”inlineRadio3”>Erro</label> </div>
</div>
</div>
<div class=”card” :class=”status”>
<div class=”card-body”>
<h5 class=”card-title”>Dados do Bem</h5>
<p class=”card-text”>
CONTRATO: @{ contrato }, </p><p> GRUPO: @{ grupo }, </p><p> COTA: @{ cota }, </p><p> VALOR: @{ valor }, </p><p> PESSOA: @{ pessoa }, </p><p> BEM CONTRATADO: @{ segmento }, </p><p> BEM ESCOLHIDO: @{ novoSegmento }, </p><p> idERP: @{ idERP }, </p>
</div>
<div class=”card-footer text-muted”>
<div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosBem” id=”inlineRadio1” value=”option1” @change=”ok”> <label class=”form-check-label” for=”inlineRadio1”>OK</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosBem” id=”inlineRadio2” value=”option2” @change=”falta”> <label class=”form-check-label” for=”inlineRadio2”>Falta</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosBem” id=”inlineRadio3” value=”option3” @change=”erro”> <label class=”form-check-label” for=”inlineRadio3”>Erro</label> </div>
</div>
</div>
<div class=”card” :class=”status”>
<div v-if=”contas != ‘’”>
<div class=”card-body”>
<h5 class=”card-title”>Dados Bancrios</h5>
<p class=”card-text”>
BANCO: @{ contas.banco }, </p>
<p> AGNCIA: @{ contas.agencia }, </p>
<p> CONTA CORRENTE: @{ contas.conta }, </p>
</div>
<div class=”card-footer text-muted”>
<div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosBancarios” id=”inlineRadio1” value=”option1” @change=”ok”> <label class=”form-check-label” for=”inlineRadio1”>OK</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosBancarios” id=”inlineRadio2” value=”option2”> <label class=”form-check-label” for=”inlineRadio2”>Falta</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosBancarios” id=”inlineRadio3” value=”option3”> <label class=”form-check-label” for=”inlineRadio3”>Erro</label> </div>
</div>
</div>
<div v-else>
<div class=”card-body”>
<h5 class=”card-title”>Dados Bancrios</h5>
<form v-on:submit.prevent=”sub” action=”#” method=”post”>
@method(‘POST’)
@csrf
<div class=”form-group”>
<label for=”banco”>Banco</label>
<input type=”text” v-model=”banco” class=”form-control” id=”banco”>
</div>
<div class=”form-group”>
<label for=”agencia”>Agncia</label>
<input type=”text” v-model=”agencia” class=”form-control” id=”agencia”>
</div>
<div class=”form-group”>
<label for=”conta”>Conta Corrente</label>
<input type=”text” v-model=”conta” class=”form-control” id=”conta”>
</div>
<button type=”submit” class=”btn btn-primary”>Cadastrar</button>
</form>
</div>
<div class=”card-footer text-muted”>
<div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosBancarios” id=”inlineRadio1” value=”option1” @change=”ok”> <label class=”form-check-label” for=”inlineRadio1”>OK</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosBancarios” id=”inlineRadio2” value=”option2”> <label class=”form-check-label” for=”inlineRadio2”>Falta</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosBancarios” id=”inlineRadio3” value=”option3”> <label class=”form-check-label” for=”inlineRadio3”>Erro</label> </div>
</div>
</div>
</div>
<div class=”card”>
<div class=”card-body”>
<h5 class=”card-title”>Dados de Patrimnio</h5>
<p class=”card-text”>
AES: @{ patrimonios.valorAcoes }, </p>
<p> AUTOMVEIS: @{ patrimonios.valorAutomovies }, </p>
<p> IMVEIS: @{ patrimonios.valorImovel }, </p>
<p> INVESTIMENTOS: @{ patrimonios.valorInvestimentos }, </p>
<p> TOTAL: @{ patrimonios.valorTotal }, </p>
</div>
<div class=”card-footer text-muted”>
<div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosPatrimonio” id=”inlineRadio1” value=”option1”> <label class=”form-check-label” for=”inlineRadio1”>OK</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosPatrimonio” id=”inlineRadio2” value=”option2”> <label class=”form-check-label” for=”inlineRadio2”>Falta</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosPatrimonio” id=”inlineRadio3” value=”option3”> <label class=”form-check-label” for=”inlineRadio3”>Erro</label> </div>
</div>
</div>
<div class=”card”>
<div class=”card-body”>
<h5 class=”card-title”>Endereos de Patrimnios</h5>
<div v-for=”imovel in imoveis”>
<p class=”card-text”>RUA: @{ imovel.rua }, </p>
<p> NMERO: @{ imovel.nroReferencia }, </p>
<p> COMPLEMENTO: @{ imovel.complementoPatrimonio }, </p>
<p> BAIRRO: @{ imovel.bairroPatrimonio }, </p>
<p> CEP: @{ imovel.cep }, </p>
<p> CIDADE: @{ imovel.cidadePatrimonio }, </p>
<p> UF: @{ imovel.UFPatrimonio }, </p>
<hr>
</div>
</div>
<div class=”card-footer text-muted”>
<div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”endPatrimonio” id=”inlineRadio1” value=”option1”> <label class=”form-check-label” for=”inlineRadio1”>OK</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”endPatrimonio” id=”inlineRadio2” value=”option2”> <label class=”form-check-label” for=”inlineRadio2”>Falta</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”endPatrimonio” id=”inlineRadio3” value=”option3”> <label class=”form-check-label” for=”inlineRadio3”>Erro</label> </div>
</div>
</div>
<div class=”card” v-if=”correspondencia != ‘’”>
<div class=”card-body”>
<h5 class=”card-title”>Endereo de Correspondncia</h5>
<div v-if=”correspondencia != ‘’”>
<p class=”card-text”>RUA: @{ correspondencia.rua }, </p>
<p> NMERO: @{ correspondencia.numero }, </p>
<p> BAIRRO: @{ correspondencia.bairro }, </p>
<p> CEP: @{ correspondencia.cep }, </p>
<p> CIDADE: @{ correspondencia.cidade }, </p>
<p> UF: @{ correspondencia.UF }, </p>
</div>
</div>
<div class=”card-footer text-muted”>
<div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”endCorrespondencia” id=”inlineRadio1” value=”option1”> <label class=”form-check-label” for=”inlineRadio1”>OK</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”endCorrespondencia” id=”inlineRadio2” value=”option2”> <label class=”form-check-label” for=”inlineRadio2”>Falta</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”endCorrespondencia” id=”inlineRadio3” value=”option3”> <label class=”form-check-label” for=”inlineRadio3”>Erro</label> </div>
</div>
</div>
<div class=”card”>
<div class=”card-body”>
<h5 class=”card-title”>Dados Profissionais</h5>
<p class=”card-text”>PROFISSO: @{ profissao.profissao }, </p>
<p> CARGO: @{ profissao.cargo }, </p>
<p> SALRIO: @{ profissao.salario }, </p>
<p> EMPRESA: @{ profissao.empresa }, </p>
<p> EMAIL: @{ profissao.emailEmpresa }, </p>
<p> CNPJ: @{ profissao.cnpj }, </p>
<p> RUA: @{ profissao.logradouro }, </p>
<p> CEP: @{ profissao.cep }, </p>
<p> Cidade: @{ profissao.cidade }, </p>
<p> UF: @{ profissao.UF }, </p>
<p> BAIRRO: @{ profissao.bairro }, </p>
<p> TELEFONE: @{ profissao.ddd } - @{ profissao.telefoneComercial } </p>
<p> RAMAL: @{ profissao.ramal }</p>
</div>
<div class=”card-footer text-muted”>
<div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosProfissionais” id=”inlineRadio1” value=”option1”> <label class=”form-check-label” for=”inlineRadio1”>OK</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosProfissionais” id=”inlineRadio2” value=”option2”> <label class=”form-check-label” for=”inlineRadio2”>Falta</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”dadosProfissionais” id=”inlineRadio3” value=”option3”> <label class=”form-check-label” for=”inlineRadio3”>Erro</label> </div>
</div>
</div>
<div class=”card”>
<div class=”card-body”>
<h5 class=”card-title”>Referncias Pessoais</h5>
<div v-for=”referencia in referencias”>
<p class=”card-text”>NOME: @{ referencia.nome }, </p>
<p> ENDEREO: @{ referencia.endereco }, @{ referencia.numero }</p>
<p> CIDADE: @{ referencia.cidade }, </p>
<p> UF: @{ referencia.UF }, </p>
<p> CEP: @{ referencia.cep }, </p>
<p> COMPLEMENTO: @{ referencia.complemento }, </p>
<p> TELEFONE: (@{ referencia.ddd }) @{ referencia.telefone }, </p>
<hr>
</div>
</div>
<div class=”card-footer text-muted”>
<div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”refPessoais” id=”inlineRadio1” value=”option1”> <label class=”form-check-label” for=”inlineRadio1”>OK</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”refPessoais” id=”inlineRadio2” value=”option2”> <label class=”form-check-label” for=”inlineRadio2”>Falta</label> </div> <div class=”form-check form-check-inline”> <input class=”form-check-input” type=”radio” name=”refPessoais” id=”inlineRadio3” value=”option3”> <label class=”form-check-label” for=”inlineRadio3”>Erro</label> </div>
</div>
</div>
</div>
How can I do it be as much as DRY as possible, and change only the card I wanna change?
Solution :
Add data elements:
data: {
oks: [],
faltas: [],
erros: []
}
Add some new logic to the methods:
falta(index) {
if (!this.faltas.includes(index)) {
this.faltas.push(index)
}
// other stuff
}
Repeat this for the erro() method.
Make sure you add the reverse logic for the ok() method:
if (this.erros.includes(index)) {
this.erros.splice(this.erros.findIndex(el => el === index), 1)
}
Dynamically change the card class based on the existence of the index:
<div class=”card” :class=”{‘bg-primary text-white’: this.faltas.includes(1)’}”>
Add any other conditionals there based on inclusion, such as for oks.includes(id) and errors.includes(id)
And update the methods for the input elements to pass the unique indexer for this card:
@change=”ok(1)”
@change=”falta(1)”
@change=”erro(1)”
And just change 1 to 2 for the next card and methods within that card and so on and so forth.
Solution 2:
You can use vue-refs to get a particular element.
Here is simple code to reproduce:
Template
<div class=”card” ref=”card-1”>
<div class=”card-body”>
…..
</div>
<div class=”card-footer text-muted”>
<input @click=”setClass(1, ‘bg-primary text-white’)”>
<input @click=”setClass(1, ‘bg-warning text-black’)”>
<input @click=”setClass(1, ‘bg-danger text-white’)”>
</div>
</div>
<div class=”card” ref=”card-2”>
<div class=”card-body”>
…..
</div>
<div class=”card-footer text-muted”>
<input @click=”setClass(2, ‘bg-primary text-white’)”>
<input @click=”setClass(2, ‘bg-warning text-black’)”>
<input @click=”setClass(2, ‘bg-danger text-white’)”>
</div>
</div>
Methods: {
setClass(index, className) {
const elem = this.$refs[`card-${index}`]
elem.className = className
}
}
Solution 3:
I would suggest to store the status on the object directly. For this to work the list used in the v-for must be inside the component data so it’s editable.
With this approach there is no need to track who has what status, indexes, etc. Each object is responsible for its own status. In this example I suppose there will be classes set up with correct styling, ok, falta and erro.
<div class=”card”>
<div class=”card-body” :class=”referencia.status”>
<h5 class=”card-title”>Referncias Pessoais</h5>
<div v-for=”referencia in referencias”>
<p class=”card-text”>
NOME: @{ referencia.nome }
</p>
…
<hr>
</div>
</div>
<div class=”card-footer text-muted”>
<button class=”some-styling-here” @click=”referencia.status = ‘ok’”> OK </button>
<button class=”some-styling-here” @click=”referencia.status = ‘falta’”> Falta </button>
<button class=”some-styling-here” @click=”referencia.status = ‘erro’”> Erro </button>
</div>
</div>