Reputation: 14317
I'm trying to automatically populate an element in an existing web page that I can't change and that page uses Knockoutjs. The input element looks like this more or less:
<input maxlength="8" id="xxx" data-bind="textInput: otcInput" type="tel">
Then I use Knockoutjs to attempt to unbind the textInput and populate the input element dynamically with whatever value I need, so I do:
ko.cleanNode($('#xxx'));
ko.applyBindings({
otcInput: ko.observable("123") // populate myself
});
However, this leads to the error You cannot apply bindings multiple times to the same element
... the question is why? I'm already cleaning the node ... or am I not? is there a way using knockoutjs to see whether there are dangling bindings or leftovers that get in the way while trying to execute my "overriding" ko.applyBindings
?
I have also tried other ways to set the input value via JQuery sendkeys plugin without success i.e.
$('#xxx').sendkeys('123'); // nothing happens
I also tried:
$('#xxx').unbind();
$('#xxx').off();
$('#xxx').sendkeys('123'); // but again nothing happens
Upvotes: 3
Views: 3688
Reputation: 1075587
You're passing a jQuery object to cleanNode
. Just like with applyBindings
, it has to be a DOM element, not a jQuery object. So:
ko.cleanNode($('#xxx')[0]);
// -------------------^^^
Example — this fails:
ko.applyBindings({
foo: ko.observable("one")
}, $("#test")[0]);
ko.cleanNode($("#test"));
ko.applyBindings({
foo: ko.observable("two")
}, $("#test")[0]);
<div id="test">
<div data-bind="text: foo"></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
...but this (with the [0]
) works:
ko.applyBindings({
foo: ko.observable("one")
}, $("#test")[0]);
ko.cleanNode($("#test")[0]);
ko.applyBindings({
foo: ko.observable("two")
}, $("#test")[0]);
<div id="test">
<div data-bind="text: foo"></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
I have also tried other ways to set the input value
If that's your goal, you don't have to muck with the bindings (which probably would have undesirable effects), just:
$("#xxx").val("new value").trigger("change");
The trigger("change")
is necessary to get KO to see the change and update the observable. (Or as it's a textInput
binding, you might use input
rather than change
.)
Example — this fails:
// The previously-bound stuff:
var vm = {
foo: ko.observable("foo")
};
ko.applyBindings(vm, document.body);
// Prove the observable and input are in sync:
console.log("check1", vm.foo(), $("#test").val());
// Update the field
$("#test").val("updated").trigger("change");
// Prove the observable and input are still in sync:
console.log("check2", vm.foo(), $("#test").val());
<input id="test" type="text" data-bind="textInput: foo">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
Upvotes: 6