简体   繁体   中英

Bind to multiple class names with Laravel & Vue.js

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM