I have 3 components. One parent component and two child components. The two child components are siblings.
Parent Component
<template>
<div >
<div >
<Modal :popupTitle="popupTitle" @addLocation="addLocation($event)"/>
<BinInfo :newBinLocation="newBinLocation"/>
<button data-bs-toggle="modal" data-bs-target="#staticBackdrop">Add new bin</button>
</div>
</div>
</template>
<script>
export default {
data(){
return{
popupTitle:"Add New Bin Location",
newBinLocation: '',
}
},
methods:{
addLocation(newBinLocation){
this.newBinLocation = newBinLocation
}
},
components:{
Navigation,
TopBtns,
BinInfo,
}
}
</script>
In one child, which is the listing component, I am showing a listing from an array
Listing Component
<template>
<div >
<h2>Bins - Location</h2>
<h5 v-if="bins.length==0">There are no bin locations added</h5>
<table v-if="bins.length > 0">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Location</th>
<th scope="col" >Action</th>
</tr>
</thead>
<tbody>
<tr v-for="(bin, index) in bins" :key="index">
<th scope="row">{{index 1}}</th>
<td><input ref="inputField" type="text" :value="bin.binlocation" :disabled="bin.disabled" @change="editedLocation=$event.target.value"></td>
<td >
<div >
<button @click="btnEdit(index)"><fa icon="edit" /> Edit</button>
<button @click="btnUpdate(index)"><fa icon="edit" /> Update</button>
<button @click="btnDelete(index)"><fa icon="trash" /> Delete</button>
</div>
</td>
</tr>
</tbody>
</table>
<div >
<router-link to="/bins">View More</router-link>
</div>
</div>
{{newBinLocation}}
</template>
<script>
export default {
data(){
return{
bins:[
{
binlocation: '11 Garden Block, New City',
disabled: true
},
{
binlocation: 'Ali Towers, Lahore',
disabled: true
},
{
binlocation: 'The Mall Road',
disabled: true
}
],
editedLocation: null,
}
},
props:['newBinLocation'],
methods:{
btnDelete(index){
this.bins.splice(index, 1)
},
btnEdit(index){
this.bins[index].disabled = !this.bins[index].disabled;
this.editedLocation = this.bins[index].binlocation
/*if(this.bins[index].disabled === false){
console.log(this.$refs.inputField)
}*/
},
btnUpdate(index){
this.bins[index].binlocation = this.editedLocation
this.bins[index].disabled = !this.bins[index].disabled
console.log(this.bins[index].binlocation)
},
btnAdd(){
let newLocation = {
binlocation: this.newBinLocation,
disabled: true
}
this.bins.push(newLocation)
}
},
}
</script>
<style scoped>
.table-responsive{
margin-bottom:25px;
}
h2{margin:0 0 15px;}
.action-btn button{
border:0;
background:#003594;
color:#fff;
margin-left:15px;
padding:3px 15px;
}
.action-btn button:hover{
background:#3490dc
}
input{
background-color:none;
border:0;
color:#000;
}
</style>
and in the second child component, I have created a modal which I am using to add a new list.
Modal Component
<template>
<div id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div >
<div >
<div >
<h5 >{{popupTitle}}</h5>
<button type="button" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div >
<p><input type="text" v-model="addBinLocation"></p>
</div>
<div >
<button @click="btnAdd" type="button" >Add Location</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props:['popupTitle'],
data(){
return{
addBinLocation: ''
}
},
methods:{
btnAdd(){
this.$emit('addLocation', this.addBinLocation)
}
}
}
</script>
<style>
</style>
I am able to add and receive the values but how can I add the new prop into the existing array so that it is added in the list.
CodePudding user response:
There is a way to add the newBinLocation
with a computed property in the Listing Component
, but it isn’t the cleanest way to do this.
You made a architecture error by declaring the bins
array in the Listing Component
. The parent component should be the one aware of the data. the Listing Component
is only here to print a list.
You should pass the array from the Parent Component
as a props. This way the Listing Component
will be easily reusable.
Once you’ve done that it’s easy to add an new item to the array.
Here is an example
Parent component
<template>
<div class="wrapper">
<div class="main-content">
<Modal :popupTitle="popupTitle" @addLocation="addLocation($event)"/>
<BinInfo :bins="bins"/> <-- You need to pass the array instead of newBinLocation -->
<button data-bs-toggle="modal" data-bs-target="#staticBackdrop">Add new bin</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
popupTitle:"Add New Bin Location",
bins:[
{
binlocation: '11 Garden Block, New City',
disabled: true
},
{
binlocation: 'Ali Towers, Lahore',
disabled: true
},
{
binlocation: 'The Mall Road',
disabled: true
}
],
}
},
methods:{
addLocation(newBinLocation){
this.bins.push(newBinLocation) // You just have to push the new value
}
},
components:{
Navigation,
TopBtns,
BinInfo,
}
}
</script>