1

I am trying to loop through and array of objects printing list items. I have a click listener which add a custom property the object and a class binding is dependent on that property value. Here is my code please have a look.

Html

<div class="row wi ony-bor-ans" v-if="q.ans" v-for="(ans,i) in q.ans" :key="i">
<div class="col-auto que-ans-main-ul">
    <ul>
        <li @click="voteOnAns(1,i)" :class="{voted:ans.ansVotedUp}">
            <i class="fa fa-chevron-up"></i>
        </li>
        <li><span>{{i}}</span></li>
        <li @click="voteOnAns(-1,i)" :class="{voted:ans.ansVotedDown}">
            <i class="fa fa-chevron-down"></i>
        </li>
    </ul>
</div>

My vue method voteOnAns looks like this

voteOnAns(ansVoteType,i){
if(ansVoteType>0){
    this.q.ans[i].ansVotedUp=true;
    this.q.ans[i].ansVotedDown=false;
}else{
    this.q.ans[i].ansVotedDown=true;
    this.q.ans[i].ansVotedUp=false;
}
console.log(this.q.ans);

}

Here this.q.ans prints the specific object correctly.

Another interesting thing is, I am using vue chrome extension and there I see some time this new property added and sometime is they are not there in object. But console.log shows the object correctly.

Any help or explanation is highly appreciated. Thank you.

2 Answers 2

2

Due to limitations of Javascript, Vue can not detect property additions so those new properties are not reactive.

You have to use Vue.set to add reactive properties dynamically:

Vue.set(this.q.ans[i], 'ansVotedUp', true);
Sign up to request clarification or add additional context in comments.

Comments

1

You cannot change the array value directly when use with Vue. What you need to do is to use Vue.set to update the value. Because Vue cannot detect the value changed when update the value with array. You may check the list rendering caveat on vue official site.

voteOnAns(ansVoteType,i){
    if(ansVoteType>0){
        Vue.set(this.q.ans[i], 'ansVotedUp', true);
        Vue.set(this.q.ans[i], 'ansVotedDown', false);
    }else{
        Vue.set(this.q.ans[i], 'ansVotedDown', true);
        Vue.set(this.q.ans[i], 'ansVotedUp', false);
    }
}

1 Comment

Thank you it worked :). I am sorry there is no way to accept two answers :) I ticked considering the first answer. Thank you once again!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.