edc
edc

Reputation: 105

KnockoutJS with nested models

I am looking for some guides on how to create the models that represent the posts in my commenting system. Essentially, it's a dumbed down version of facebook where there are posts by different users, and each post will have zero or more comments. There's always only one level of parent-child relationship.

I have no problem creating the Post object, but I need some help on creating and binding the comments that nest below a post. If I have a Post model and a Comment model, how do I tie the two together?

I tried google around but I couldn't find a good example on data-binding with nested model.

Sample JSON to give you a good idea on how the object looks like:

`{
  "PostedBy": 1,
  "CommentedByFirstName": "John",
  "CommentedByLastName": "Smith",
  "CommentedByGravatar": "[email protected]",
  "Category": "General",
  "CategoryColor": "0076c0",
  "Message": "This is a parent",
  "PostedDate": "2015-06-18T19:32:51.487",
  "PostId": 1008,
  "Anchor": {
    "AnchorId": 9,
    "DashboardId": "1da42665-1cf3-431c-924e-5ed0575315d7"
  },
  "PostComment": [
    {
      "CommentedBy": 1,
      "CommentedByFirstName": "John",
      "CommentedByLastName": "Smith",
      "CommentedByGravatar": "[email protected]",
      "CommentedDate": "2015-06-23T20:28:10.887",
      "CommentId": 19,
      "Message": "test5",
      "PostId": 1008
    },
    {
      "CommentedBy": 1,
      "CommentedByFirstName": "John",
      "CommentedByLastName": "Smith",
      "CommentedByGravatar": "[email protected]",
      "CommentedDate": "2015-06-18T20:54:33.533",
      "CommentId": 18,
      "Message": "test4",
      "PostId": 1008
    },
    {
      "CommentedBy": 1,
      "CommentedByFirstName": "John",
      "CommentedByLastName": "Smith",
      "CommentedByGravatar": "[email protected]",
      "CommentedDate": "2015-06-18T20:54:30.75",
      "CommentId": 17,
      "Message": "test3",
      "PostId": 1008
    }
  ]
}`

Upvotes: 0

Views: 79

Answers (1)

Matt Burland
Matt Burland

Reputation: 45155

If I have a Post model and a Comment model, how do I tie the two together?

Your PostVM will have a Comments property that is an array of CommentVMs. You can bind it with a simple foreach binding. Something like this:

var post = {
  "PostedBy": 1,
  "CommentedByFirstName": "John",
  "CommentedByLastName": "Smith",
  "CommentedByGravatar": "[email protected]",
  "Category": "General",
  "CategoryColor": "0076c0",
  "Message": "This is a parent",
  "PostedDate": "2015-06-18T19:32:51.487",
  "PostId": 1008,
  "Anchor": {
    "AnchorId": 9,
    "DashboardId": "1da42665-1cf3-431c-924e-5ed0575315d7"
  },
  "PostComment": [
    {
      "CommentedBy": 1,
      "CommentedByFirstName": "John",
      "CommentedByLastName": "Smith",
      "CommentedByGravatar": "[email protected]",
      "CommentedDate": "2015-06-23T20:28:10.887",
      "CommentId": 19,
      "Message": "test5",
      "PostId": 1008
    },
    {
      "CommentedBy": 1,
      "CommentedByFirstName": "John",
      "CommentedByLastName": "Smith",
      "CommentedByGravatar": "[email protected]",
      "CommentedDate": "2015-06-18T20:54:33.533",
      "CommentId": 18,
      "Message": "test4",
      "PostId": 1008
    },
    {
      "CommentedBy": 1,
      "CommentedByFirstName": "John",
      "CommentedByLastName": "Smith",
      "CommentedByGravatar": "[email protected]",
      "CommentedDate": "2015-06-18T20:54:30.75",
      "CommentId": 17,
      "Message": "test3",
      "PostId": 1008
    }
  ]
};

function PostVM(postObj) {
    var self = this;
    self.message = postObj.Message;
    // ... other properties
    self.comments = postObj.PostComment.map(function(c) {
        return new CommentVM(c);
    });
};

function CommentVM(commentObj) {
    var self = this;
    self.message = commentObj.Message;
    // ... other properties
};

var vm = new PostVM(post);
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="text:message">
</div>
<hr/>
<ul data-bind="foreach:comments">
    <li data-bind="text:message"/>
</ul>

I used plain properties here just for simplicity, but obviously you can use observables (including an observable collection for the comments) for any properties that are supposed to be writable or updateable.

You should also look at the mapping plugin that would, with one line, basically transform your whole post object into a view model with observables. This saves you a lot of manual mapping of properties.

Upvotes: 1

Related Questions