0

I have a button with a html binding which I render at the beginning. The reason I want to render this button like this is because I want to delete this button (delete, not remove visibility) later.

By script is as follows:

<script type="text/javascript">
               function AppViewModel() {
                    var self = this;
                    self.addButton = ko.observable();
                    var button = "<button class='btn btn-primary btn-lg' type='button' data-bind=\"click: buttonClicked, customVal: val\"> Add button</button>";
                    self.addButton(button); 


                    self.buttonClicked = function() {
                        alert('Button clicked');
                    };
                }

                $( document ).ready(function() {
                        ko.applyBindings(new AppViewModel());          
                    });

            </script>

My HTML is:

<div class="col-md-6">
              <div id="addButt" data-bind="html: addButton"></div>
</div>

Now when I load the page the button is correctly rendered but when I click it nothing happens. It doesn't call the 'buttonClicked' method.

My understanding is that this is because the DOM is not updated to this new button when bindings are applied.

Is there anyway to re-apply the bindings with the new DOM?

Cheers.

madu
  • 5,232
  • 14
  • 56
  • 96
  • 1
    There are bindings like `if` or `with` which are removing the elements from the DOM... Also I don't get what is the relation between the dynamic rendering and the later removal... – nemesv Jul 29 '14 at 15:34
  • 1
    I agree with nemesv, binding html in this way is not really how knockout was intended. There isn't really a way to refresh bindings. See: http://stackoverflow.com/q/8281875/1061602 – Adam Marshall Jul 29 '14 at 16:23
  • Thank you very much nemesv, Adam. I think it is best I use JQuery for adding/deleting buttons. But I'm not sure how I can add a button dynamically and also provide a 'data-bind' attribute to it through JQuery. – madu Jul 29 '14 at 23:12

1 Answers1

1

You can get what you're trying to do to work by using ko.cleanNode on the button after you insert it. Here's a fiddle:

http://jsfiddle.net/2aKRS/

and the code, tweaked slightly:

function AppViewModel() {
    var self = this;
    self.addButton = ko.observable("");
    self.buttonClicked = function() {
        alert('Button clicked');
    };
}

$( document ).ready(function() {
    // Initially, there is no button.
    var avm = new AppViewModel();
    ko.applyBindings(avm, $("#addButt")[0]);

    // Now, create the button and clean and reapply KO to the button itself.
    avm.addButton("<button class='btn btn-primary btn-lg' type='button' data-bind=\"click: buttonClicked\"> Add button</button>");
    ko.cleanNode($("#addButt button")[0]);
    ko.applyBindings(avm, $("#addButt button")[0]);
});

So basically every time you change your button HTML, you need to clean the button node, then reapply bindings to just that node.

sifriday
  • 4,342
  • 1
  • 13
  • 24