I'm trying to understand Knockout JS. What bothers me is that the data I bind gets blanked out. It's annoying because I want to show the data I retrieve from the server.
An example:
Name: <span class="name"><?php echo $data->name; ?></span>
The result is: Name: John B
Now if I data-bind this with Knockout to this:
Name: <span data-bind="text: name" class="name"><?php echo $data->name; ?></span>
The result is: Name:
The JS will be something like:
var viewModel = {
name: ko.observable() // Initially blank <--- this is the culprit
};
ko.applyBindings(viewModel);
So what do I need to do in order to show / keep the data?
Can't Knockout somehow keep the data like Angular JS does?
Note I'm using Yii MVC framework to handle a lot of server side stuff. Using that to load data on page load, saves me from writing a lot of JS Ajax code. I wanted to use Knockout to reduce the amount of jQuery code I have, not add to it :)
Another alternative is to construct your viewmodel supplying your value from the server directly into the observable.
Trying to initialise an observable's value from the HTML is dangerous as there are many ways that the observable's value will be reset, specifically if an element is contained within a parent binding that uses a explicit/implicit template, like an
if
binding.In the above example, everytime the
someFlag
value changes from false to true, the text binding on the span element will be re-initialised.Here are two workaround you can try to avoid declaring your data twice (note that they do not directly provide a way to keep your data in your html file) :
Solution 1: Put your default model in a separate js/php file
Create a php file with:
Then you include this php file as a js file and init your viewmodel with it:
Solution 2: Use the ko.mapping plugin
Create a php file with:
Then in your js, you can use the ko.mapping plugin:
This allows you to get your data asynchronously (if you want) with something like:
You can create a custom binding handler to do this:
And then you can bind to your viewmodel like this:
EDIT after jsFiddle:
You have created a completely different thing in the jsFiddle. A few things:
element.value
instead ofelement.innerHTML
.I have modified the fiddle with these changes: http://jsfiddle.net/P8N77/24/