Tratando de mostrar dinámicamente los campos de entrada solo para una iteración específica; actualmente muestra los campos de entrada para todos ellos. También he preparado este violín stackblitz.
Actualmente, cuando hago clic en "agregar usuario a Estocolmo", se muestran todos los campos de entrada y todos los campos de entrada se completan cuando escribo el nombre del nuevo usuario.
<div v-for="(city, a) in cities" v-bind:key="city.name" style="margin-bottom: 30px" > {{ city.name }} <div v-for="(user, b) in city.users" :class="[user.active ? 'green' : 'red']" > {{ user.name }} {{ b }} <button v-on:click="deleteUser(a, b)">Delelete</button> <button v-on:click="activateUser(a, b)"> {{ user.active ? 'Unactive' : 'Active' }} </button> </div> <div v-if="addUser" style="margin-top: 10px"> <input type="text" v-model="newUserName" placeholder="name" /> <button v-on:click="addUserToArray(a)" class="green">Add</button><br /> </div> <br /> <button v-on:click="addUser = !addUser"> {{ addUser ? 'Close' : `Add user to ${city.name}` }} </button> </div> data() { return { cities: [ { name: 'Stockholm', users: [ { name: 'Johan', active: true }, { name: 'Adam', active: false }, { name: 'Anders', active: false }, ], }, { name: 'New York', users: [ { name: 'Andy', active: true }, { name: 'Mitchell', active: false }, { name: 'Steve', active: false }, ], }, { name: 'San Jose', users: [ { name: 'Riana', active: true }, { name: 'Rita', active: false }, { name: 'Montgomery', active: false }, ], }, ], addUser: false, newUserName: '', }; },Simplemente reemplace booleano con índice:
const app = Vue.createApp({ data(){ return { cities: [{name: 'Stockholm', users:[{name: 'Johan', active: true}, {name: 'Adam', active: false}, {name: 'Anders', active: false}]}, {name: 'New York', users:[{name: 'Andy', active: true}, {name: 'Mitchell', active: false}, {name: 'Steve', active: false}]}, {name: 'San Jose', users:[{name: 'Riana', active: true}, {name: 'Rita', active: false}, {name: 'Montgomery', active: false}]}], addUser: null, newUserName: '' } }, computed: { activeUser: function(){ return this.cities.map((city) => { return city.users.filter(function(q){ return q.active }) }).flat() } }, methods: { // 👇 save user index selectUser(idx) { this.addUser === idx ? this.addUser = null : this.addUser = idx }, activateUser(a,b){ this.cities[a].users[b].active = !this.cities[a].users[b].active }, deleteUser(a,b){ this.cities[a].users.splice(b) }, addUserToArray(a){ if(this.newUserName == ''){ return false } this.cities[a].users.push({name: this.newUserName, active:false}) this.newUserName = '' this.addUser = false }, deActiveAllUsers(){ this.cities.map((city) => { return city.users.forEach(element => element.active = false) }) }, }, }) app.mount('#demo') <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script> <div id="demo"> <h1>All users</h1> <div v-for="(city, index) in cities" :key="index" style="margin-bottom: 30px"> {{city.name}} <div v-for="(user, b) in city.users" :class="[user.active ? 'green' : 'red']"> {{user.name}} {{b}} <button @click="deleteUser(index, b)">Delelete</button> <button @click="activateUser(index, b)">{{user.active ? 'Unactive' : 'Active'}}</button> </div> <!-- 👇 compare user index --> <div v-if="addUser === index" style="margin-top: 10px;"> <input type="text" v-model="newUserName" placeholder="name"/> <button @click="addUserToArray(index)" class="green">Add</button><br> {{newUserName}} </div> <br> <!-- 👇 save user index --> <button @click="selectUser(index)">{{addUser === index ? 'Close' : `Add user to ${city.name}`}}</button> </div> <button @click="deActiveAllUsers">Deactiev all users</button> <h1>Active users</h1> <div v-if="activeUser.length > 0"> <div v-for="user in activeUser">{{user.name}}</div> </div> <div v-else> No active users </div> </div>Observación/Sugerencia :
Como los campos de entrada serán dinámicos en función del clic del botón Add user to city . Por lo tanto, v-model debe ser único para que cuando intente agregar al usuario en una ciudad diferente, no conserve el valor del modelo v ingresado anteriormente, ya que todos comparten el mismo nombre.
En plantilla :
<input type="text" v-model="newUserName[a]" placeholder="name" />En objeto de datos :
newUserName: [] Simplemente puede lograrlo simplemente asignando el index a la variable (addUser = a) al hacer clic en el botón.
Demostración de trabajo :
new Vue({ el: '#app', data: { cities: [ { name: 'Stockholm', users: [ { name: 'Johan', active: true }, { name: 'Adam', active: false }, { name: 'Anders', active: false }, ], }, { name: 'New York', users: [ { name: 'Andy', active: true }, { name: 'Mitchell', active: false }, { name: 'Steve', active: false }, ], }, { name: 'San Jose', users: [ { name: 'Riana', active: true }, { name: 'Rita', active: false }, { name: 'Montgomery', active: false }, ], }, ], addUser: null, newUserName: [] } }) <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <div v-for="(city, a) in cities" v-bind:key="city.name" style="margin-bottom: 30px"> {{ city.name }} <div v-for="(user, b) in city.users" :class="[user.active ? 'green' : 'red']"> {{ user.name }} {{ b }} <button v-on:click="deleteUser(a, b)">Delelete</button> <button v-on:click="activateUser(a, b)"> {{ user.active ? 'Unactive' : 'Active' }} </button> </div> <div v-if="addUser === a" style="margin-top: 10px"> <input type="text" v-model="newUserName[a]" placeholder="name" /> <button v-on:click="addUserToArray(a)" class="green">Add</button><br /> </div> <br/> <button v-on:click="addUser = a"> {{ addUser === a ? 'Close' : `Add user to ${city.name}` }} </button> </div> </div>