Kristoffer Abell Kristoffer Abell - 2 months ago 7
HTML Question

forEach with object properties in KnockoutJS

I have found a few answer regarding this but has not been able to put things together. First day of using Knockout so please let me know if I am thinking about it completely wrong!

I want to represent a list of comments that I have. The comments contain multiple attributes such as {text: ..., score: ..., ...}

I understand that I have a view model



var MatchupViewModel = function(comments) {
this.comments = ko.observableArray(comments);
}

ko.applyBindings(new MatchupViewModel(comments), document.getElementById("leftchat"));





And I understand that the forEach looks somewhat like this:


  • in jade (which I am using:





#leftchat.chat(data-bind="forEach: comments")
.fullMessage
.content
p.textcontent(data-bind="text: text, visible: text")
img.imagecontent(data-bind="visible: isImage, attr={src: url}")
.scorecontainer
.buttonContainer
p.likeButtonMessage(bind-data="click=voteComment(id, true)") &#x25B2
p.dislikeButtonMessage(bind-data="click=voteComment(id, false)") &#x25BC
p.messageScore(data-bind="text: score")





translated to html:



<div id="leftchat" data-bind="forEach: comments" class="chat">
<div class="fullMessage">
<div class="content">
<p data-bind="text: text, visible: text" class="textcontent"></p><img data-bind="visible: isImage, attr={src: url}" class="imagecontent"/>
</div>
<div class="scorecontainer">
<div class="buttonContainer">
<p bind-data="click=voteComment(id, true)" class="likeButtonMessage">&#x25B2</p>
<p bind-data="click=voteComment(id, false)" class="dislikeButtonMessage">&#x25BC</p>
</div>
<p data-bind="text: score" class="messageScore"></p>
</div>
</div>
</div>





It complains that text is not a function, which is the attribute I had hoped it would have been able to find. How do I work around this?

Answer

If you fix the typo's you code should work. forEach should be foreach, and bind-data should be data-bind (unless you made it a custom binding). Have a look at the example below. When text is a falsy value (null, empty string), the node will be hidden, else its value will be visible. This holds true for observable properties too.

var m = {
  comments: [
    {text: 'a'},
    {text: ko.observable('') },
    {text: null},
    {text: ko.observable('c')}
  ]
};

ko.applyBindings(m);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div id="leftchat" data-bind="foreach: comments" class="chat">
  <div data-bind="text: text, visible: text" class="textcontent"></div>
</div>