goodson
goodson

Reputation: 757

How to make a class's "virtual" getter reactive in VueJS

I have a BlogPost object and a Comment object that look roughly like this:

class Comment {
  constructor (blogId, text) {
    this.blogId = id
    this.text = text
  }
}

class BlogPost {
  constructor (id, text) {
    this.id = id
    this.text = text
  }
  get comments () {
    return commentCollection.filter(comment => comment.blogId === this.id)
  }
}

I want the comments getter to seem like a reactive property. Given a vue like this...

<template>
  <div>
    <h1>The post has {{myBlogPost.comments.length}} comments</h1>
    <v-btn @click="addComment()">Add Comment</v-btn>
  </div>
</template>

<script>

export default {
  data () {
    return {
      myBlogPost: null
    }
  },
  methods: {
    let newComment = new Comment('myBlogId_0', 'This is a comment on hello world')
    commentCollection.splice(0, 0, newComment)
  },
  mounted () {
    this.myBlogPost = new BlogPost('myBlogId_0', 'Hello World')
  }
}
</script>

... I'd like to have comment count updated when the user adds a comment. How is this done? I can't make the BlogPost comment collection reactive, because it's not really a property.

I've tried adding a computed method to the vue which calls the "getter" on BlogPost, but that doesn't seem to setup a dependency with the comments collection. And Vue.set() doesn't seem to offer help. Where could I "set" something to get vue to react?

The only idea I have (which I think will work) is to setup a watcher on the comments collection and have that watcher update some other value in data by calling the comments getter, but I might have dozens of these situations within the same objects and others. I'd like to avoid writing so many watchers and keeping so much extra state in data. Any ideas? Thanks/

Upvotes: 1

Views: 410

Answers (1)

muka.gergely
muka.gergely

Reputation: 8329

This may help a bit:

<template>
  <div>
    <h1>The post has {{myBlogPost.comments.length}} comments</h1>
    <v-btn @click="addComment">Add Comment</v-btn>
  </div>
</template>

<script>

export default {
  data () {
    return {
      myBlogPost: {
        comments: []
      }
    }
  },
  methods: {
    addComment() {
      let newComment = new Comment('myBlogId_0', 'This is a comment on hello world')
      // commentCollection is not defined in this snippet
      commentCollection.splice(0, 0, newComment)
      this.myBlogPost.comments.push( newComment )
    }
    // let newComment = new Comment('myBlogId_0', 'This is a comment on hello world')
    // commentCollection.splice(0, 0, newComment)
  },
  mounted () {
    this.myBlogPost = new BlogPost('myBlogId_0', 'Hello World')
  }
}
</script>

Upvotes: 1

Related Questions