4

I am trying to add a "data-bind" attribute to a div using jQuery as follows:

var messageViewModel = {
    data: ko.observable({   
        message: response.message, 
        sendDateFmted: response.sendDateFmted, 
        messageId: response.messageId
    })
     };

$("<div>",{
    class:"messageToAndFromOtherMember"
}).data("bind", "template: { name: 'message-template', data: data }").appendTo("#messagesToAndFromOtherMember");

ko.applyBindings(messageViewModel);

"data-bind" is required by KnockoutJs. However all I get is this empty div:

<div class="messageToAndFromOtherMember"></div>

Notice there is no such attribute as data-bind and therefore the div remains empty...

Alexander
  • 23,432
  • 11
  • 63
  • 73
balteo
  • 23,602
  • 63
  • 219
  • 412
  • 1
    +1 for a usefull question as this is a common issue. When writing data using `.data()` it will not update any elements, it will merely store data in memory for that element in a key-value pair format, in your case `bind`. being the key and the rest being the value. See the [data-documentation](http://api.jquery.com/data/) for more details. – Nope Dec 02 '12 at 20:32

2 Answers2

8

jQuery's .data() stores the values in-memory and uses data-* attributes for initialization. You may want to stick by setting it at element creation.

$("<div/>", {
  class: "messageToAndFromOtherMember",
  "data-bind": "template: { name: 'message-template', data: data }"
}).appendTo("#messageToAndFromOtherMember");
Alexander
  • 23,432
  • 11
  • 63
  • 73
  • 1
    +1 for explaining that `.data()` stores the values in memory. It can be confusing sometimes as when calling `.data()` it will read data attributes of elements and store them in memory and as far as I know it will use the in-memory storage for any consecutive call thereafter. When updating the data using `.data()` it will not write back to the elements but merely update the in-memory stored data. – Nope Dec 02 '12 at 20:30
2

Alexander's answer is definitely correct, in the general sense, but I couldn't help but notice that in your specific example you seem to be adding messages to your code by creating a new binding scope for each message. If this is the case, I think you are using Knockout incorrectly (if not, let me know and I will just remove this).

If you are getting new messages from a server, and just trying to display the list of them on the page, a much better structure would be to use an ObservableArray, and simply push new messages to it. The standard knockout binding will automatically add the new messages to your html, without the mess of creating a new binding scope, and a completely independent viewmodel for the new message. You can see this in action in this fiddle.

Here is the rather contrived ViewModel:

var ViewModel = function(data) {
    var self = this;
    self.messages = ko.observableArray();
    self.newMessage = ko.observable('');
    self.addMessage = function() {
        var message = new Message({ message: self.newMessage()});
        self.newMessage('');
        self.messages.push(message);
    };
};
Kyeotic
  • 19,697
  • 10
  • 71
  • 128
  • Tyrsius, I am rather new to KO. Thanks a lot for your reply. I will definitely consider this alternative. – balteo Dec 03 '12 at 06:10
  • 1
    @balteo I figured. We are all new at some point. I would take some time to go through the [knockout tutorials](http://learn.knockoutjs.com/), they might help you understand the pattern a little better. – Kyeotic Dec 03 '12 at 06:12
  • I will do so. Thanks for the link. – balteo Dec 03 '12 at 08:48