0

I have the need to generate the content of an element dynamically. This would be fine if I just needed text. I could just use a computed observable to build the string. The part I'm struggling with is that I need to output some links as well. I'd like these links to have the same binding as if I had done a click binding on the anchor element. Is this possible to do in knockout? If not, what are some solutions for this problem. Currently I'm just making a separate template for each of the CURRENT 13 possibilities, but this is very ugly and I'd like to avoid it if at all possible.

edit

So basically I want to output this from a computed observable and have it bound to the same viewmodel that the computed observable is bound to:

Some text with a <a href="javascript:void(0)" data-bind="click: ViewModelMethod">link</a>

LordZardeck
  • 7,953
  • 19
  • 62
  • 119

2 Answers2

1

I think you want to dynamically generate link which will have click binding. i have tried out something like this.

viewmodel:-

var Vm = {
  showMsg: function () {
    alert("hello");
  },
  Link: ko.observable("")
}

Vm.GenratedLink = ko.computed(function () {
  if (this.Link() && this.Link() !== "") {
      $("#vm").append("<a id='link' href='javascript:void(0)' data-bind='click: showMsg'>" + this.Link() + "</a>");
      ko.applyBindings(Vm, $("#link")[0]);
}
}, Vm);
ko.applyBindings(Vm);

view

 <div id="vm">Link
    <input type="text" data-bind="value: Link"/>
 </div>

hope it will work :)

Fiddle Demo

Akhlesh
  • 2,389
  • 1
  • 16
  • 23
  • We don't use id's and are trying to stay away from jQuery. This is an interesting idea though, too bad that knockout only allows innerHtml and not append... – LordZardeck Mar 18 '14 at 18:45
  • thanks for the point in the right direction though, see my answer for how I got it working using your advice – LordZardeck Mar 18 '14 at 19:30
0

Ok, thanks to @akhlesh I found something that will probably work. The only thing I'm having issues with is that the click event is being fired twice, but that's a seperate question (see Why is this event being handled twice in knockout?). Here's how I did it:

ko.bindingHandlers.activityContent = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // This will be called when the binding is first applied to an element
        // Set up any initial state, event handlers, etc. here
        var content = document.createElement("p");
        content.innerHTML = '<a href="javascript:void(0)" data-bind="text: user_name, click: $parent.NavigatePage.bind($data, \'profile\', user_id)"></a>';
        element.appendChild(content);
        ko.applyBindings(bindingContext, content);
    },
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // This will be called once when the binding is first applied to an element,
        // and again whenever the associated observable changes value.
        // Update the DOM element based on the supplied values here.
    }
};

var activities = ko.mapping.fromJS({Activities: [{
    "user_id": "52b5042d572b94ceadf6asdf1a2a5bc",
    "user_name": "Sean Templeton"
}, {
    "user_id": "52b5042d57asfda2b94ce61a2a5bc",
    "user_name": "Sean Templeton"
}, {
    "user_id": "52b5042d572b94ce61a2a5bc",
    "user_name": "Sean Templeton"
}, {
    "user_id": "52b5042d5asdfasdf72b94ce61a2a5bc",
    "user_name": "Sean Templeton"
}, {
    "user_id": "52basdf5042d572b94ce6asdf1a2a5bc",
    "user_name": "Sean Templeton"
}], NavigatePage: function(page, userId) { console.log(this); console.log(page); console.log(userId()); }});

ko.applyBindings(activities);

and the html:

<ul data-bind="foreach: Activities">
    <li data-bind="activityContent: $data"></li>
</ul>
Community
  • 1
  • 1
LordZardeck
  • 7,953
  • 19
  • 62
  • 119