I have this simple div:
<div id="mainContent">
</div>
and it's empty. Now I'm trying to append this HTML
to the above div:
<div id="mainContent">
<label>Project Name</label>
<input type="text" id="projectName" data-bind="value: projectName"/>
<label>Tracker Name</label>
<input type="text" id="trackerName" data-bind="value: trackerName"/>
</div>
<button type="submit" data-bind="click: submitNewProject">Submit</button>
By using:
$.ajax({
type : 'POST',
url : 'newTracker.php',
dataType : 'html',
success : function(data){
$("#mainContent").html(data);
},
error : function(XMLHttpRequest, textStatus, errorThrown) {
alert('Something is wrong!');
}
});
Where data
is the HTML
I'm trying to assign by: $("#mainContent").html(data);
At first look everything looks pretty, but there is a problem - the bindings are not working.
What I mean is that in the newly assigned HTML
I have a button supposed to call a viewmodel function, but it does not...
BUT if I place the code directly inside of the div the bindings are working like a charm.
Why my bidings are not working when I'm assigning a new HTML
code inside of the div? I know that I'm missing something really small and basic here, but I can't spot it.
EDIT:
Button event:
submitNewProject = function(){
console.log("submit new project");
};
I have this simple div:
<div id="mainContent">
</div>
and it's empty. Now I'm trying to append this HTML
to the above div:
<div id="mainContent">
<label>Project Name</label>
<input type="text" id="projectName" data-bind="value: projectName"/>
<label>Tracker Name</label>
<input type="text" id="trackerName" data-bind="value: trackerName"/>
</div>
<button type="submit" data-bind="click: submitNewProject">Submit</button>
By using:
$.ajax({
type : 'POST',
url : 'newTracker.php',
dataType : 'html',
success : function(data){
$("#mainContent").html(data);
},
error : function(XMLHttpRequest, textStatus, errorThrown) {
alert('Something is wrong!');
}
});
Where data
is the HTML
I'm trying to assign by: $("#mainContent").html(data);
At first look everything looks pretty, but there is a problem - the bindings are not working.
What I mean is that in the newly assigned HTML
I have a button supposed to call a viewmodel function, but it does not...
BUT if I place the code directly inside of the div the bindings are working like a charm.
Why my bidings are not working when I'm assigning a new HTML
code inside of the div? I know that I'm missing something really small and basic here, but I can't spot it.
EDIT:
Button event:
submitNewProject = function(){
console.log("submit new project");
};
Share
Improve this question
asked Jun 10, 2014 at 13:14
SlimSlim
1,7445 gold badges38 silver badges61 bronze badges
5
- 1 Can you show the code for the bindings? – Smeegs Commented Jun 10, 2014 at 13:15
- 1 Possible dupe? stackoverflow./questions/11066732/…. Dynamically added content will not be in the VM so you have to (re)apply your bindings. – Stevangelista Commented Jun 10, 2014 at 13:15
-
2
can you show us the eventhandler of the button? i gues you are not using delegates using the
on()
– Mivaweb Commented Jun 10, 2014 at 13:15 - 2 You should use delegation. – Ionică Bizău Commented Jun 10, 2014 at 13:16
- @VDesign just placed it. – Slim Commented Jun 10, 2014 at 13:16
3 Answers
Reset to default 5Knockout cannot track newly created elements, if your DOM changed using Ajax methods you'll have to explicitly bind a view-model to the newly created elements.
Something like:
$.ajax({
type: 'POST',
url: 'newTracker.php',
dataType: 'html',
success: function (data) {
var $mainContent = $("#mainContent");
$mainContent.html(data);
var existingViewModel = ko.dataFor(document.body);
ko.applyBindings(existingViewModel, $mainContent.get(0));
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert('Something is wrong!');
}
});
As most have pointed out. When you add the HTML dynamically with the append, the DOM isn't reevaluating the bindings. So, you need to either:
- apply/reapply your bindings in the .ajax
success
event handler - apply/reapply your bindings in a
document
htmlonChange
handler - place your HTML statically in the first place but use a class for all the elements that has a style of set the
display:none
, then change the style todisplay:block
,display:inline-block
, etc.. - use a hybrid of above with some static HTML to at least establish the binding between the button and function and anything else that will be required to make the bindings work, but then dynamically
.append()
anything else that is not dependent on the binding
Sometimes you need to create a secondary function on the parent page to apply the bindings and then call that function from within the appended text. All the functions defined on the original page as it loads will be available. I have used this method before, though you have to know in advance what functions you will need to build. Or you can just include the binding as part of the post-ajax process.
It makes ajax loads with decent functionality
function bindStuff() {
$(".class1").click(function() {
// do something with the bind
});
}
function ajaxLoad() {
// Perform ajax load
// on plete call your bindings
plete: function() {
bindStuff();
}
}
With your example:
$.ajax({
type : 'POST',
url : 'newTracker.php',
dataType : 'html',
success : function(data){
$("#mainContent").html(data);
},
plete: function(){
bindStuff();
},
error : function(XMLHttpRequest, textStatus, errorThrown) {
alert('Something is wrong!');
}
});