I have a vue component that displays a list of items. I can flag any item as "active" (boolean value). That value is saved to a database.
For example, I could have five total items. Three of them could be marked as "active" the remaining two are not.
When my page loads, the active/not active data is coming from my controller and I am passing data to my vue component as a property. The property has an attribute active
that can be toggled on/off. That value is stored in a database as a boolean.
This is what my component looks like:
<template>
<div class="item" :class="{'active' : isActive}" @click="handleClick($event, item)">
<div v-if="item.icon" class="item-icon">
<i :class="item.icon"></i>
</div>
<div class="item-title">
{{ item.title }}
</div>
</div>
</template>
<script>
export default {
name: 'Item',
data() {
return {
isActive: false,
}
},
methods: {
async handleClick(event, item) {
try {
let response = await axios.patch(`/path/${item.id}`, {
title: item.title,
active: !this.isActive,
});
if (response.status === 200) {
this.isActive = !this.isActive;
console.log('isActive: ', this.isActive);
} else {
console.error('Error: could not update item. ', response);
}
} catch (error) {
console.error('Error: sending patch request. ', error);
}
},
},
props: {
item: {
type: Object,
required: true,
},
},
}
</script>
Overall, the system is working. My request(s) are getting handled correctly and data is getting updated correctly.
If I change my template to this:
<div class="item" :class="{'active' : isActive}"
@click="handleItemClick($event, item)">
I am seeing the class/ui update correctly. But, because the initial data is coming from Laravel (controller) I need to have the two classes.
So somehow I am not binding to the classes correctly so that when I click, the ui is getting updated correctly.
EDIT
Thank you so much for your suggestions. I updated my component logic to reflect what is working properly. When things fall apart is when I change the template to account for if an item is already active:
<div class="item" :class="{'active' : isActive, 'active': item.active}"
@click="handleClick($event, item)">
The logic still works (when I refresh the page) but the UI doesn't update dynamically.
You can setup a computed property that accounts for the item.active
and for isActive
in your component, like:
computed: {
bindActive() {
return this.isActive || this.item.active;
}
}
So you can setup only one class in your template syntax:
<div class="item" :class="{'active' : bindActive}" @click="handleItemClick($event, item)">...</div>
First I want to thank everyone for their suggestions; it was a tremendous help!
I hope that I can help others with this so here is what I came up with.
<template>
<div class="item" :class="{'active': isActive}"
@click="handleClick($event, item)">
<div v-if="item.icon" class="item-icon">
<i :class="item.icon"></i>
</div>
<div class="item-title">
{{ item.title }}
</div>
</div>
</template>
<script>
export default {
name: 'Item',
data() {
return {
isActive: this.item.active, // <-- this was my error
}
},
methods: {
async handleClick(event, item) {
try {
let response = await axios.patch(`/path/${item.id}`, {
title: item.title,
active: !this.isActive,
});
if (response.status === 200) {
this.isActive = response.data.item.active;
} else {
console.error('Error: could not update item. ', response);
}
} catch (error) {
console.error('Error: sending patch request. ', error);
}
},
},
props: {
item: {
type: Object,
required: true,
},
},
}
Hope this helps someone!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.