forever_software
forever_software

Reputation: 145

Object value is changed but component is not updated

I am using Vue (2.0) in my project. WorkingArea component get a object via props. Words in the object are rendered by 'vfor' in WorkingArea component and they are create a sentence. I add external field named "status" the object in before component mounted. Object status can be active or inactive. I think that when status is active, color of word is changed red. Although the object is updated, component did not triggered for rendering. I'm sharing below WorkingArea component:

<template>
    <div id='sentence' class="drtl mt-3">
       <p  :class="word.status == 'active' ? active : inactive" v-for="(word, index) in hadithObject.hadith_words" :key="index" :id='index'>
           {{ word.kelime}}
       </p>
    </div>
    <b-button variant="danger" @click="nextWord()" >next</b-button>
</template>

<script>
export default {
    props: {
        hid:String,
        ho: Object,
    },
    data() {
        return {
            hadithObject: null,
            cursor: 0,
            //css class binding.
            inactive: 'inactive',
            active: 'active',
        }
    },
    beforeMount () {
        this.hadithObject = this.ho;
        this.hadithObject.hadith_words.forEach(item => {
            item.status = this.inactive;
        });
    },
    nextWord(){
         // when click to button, status of word is set active.
         this.hadithObject.hadith_words[this.cursor].status = this.active;
         this.cursor += 1;
    }
</script>

<style lang="scss" scoped>
@import url('https://fonts.googleapis.com/css?family=Amiri&display=swap');

.inactive{
    font-family: 'Amiri', serif;
    font-size: 23px;
    line-height: 2.0;
    display: inline-block;
    color: black;
}
.drtl{
    direction: rtl;
}

.active{
    color: red;
    font-family: 'Amiri', serif;
    font-size: 23px;
    line-height: 2.0;
    display: inline-block;
}
</style>

-------UPDATED FOR SOLUTION--------

After @Radu Diță answers, I examine shared this link. I learned that Vue cannot detect the following changes to an array:

  1. When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue
  2. When you modify the length of the array, e.g. vm.items.length = newLength

My mistake is trying first item. "newtWord" method is updated like below:

nextWord(){    
   var newItem = this.hadithObject.hadith_words[this.cursor];
   newItem.status = this.active;
   this.$set(this.hadithObject.hadith_words,this.cursor,newItem);
   this.cursor += 1;
}

Upvotes: 0

Views: 302

Answers (1)

Radu Diță
Radu Diță

Reputation: 14171

You are updating hadithObject's keys. They are not reactive as they aren't added from the beginning.

Look over the caveats regarding reactivity.

You have 2 options:

  • either assign the object again this.hadithObject = Object.assign({}, ...this.hadithObject)
  • use Vue.set to set the new keys on the object.

Upvotes: 1

Related Questions