How do I keep data loaded from the server from get

2019-08-07 02:28发布

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 :)

3条回答
不美不萌又怎样
2楼-- · 2019-08-07 03:09

Another alternative is to construct your viewmodel supplying your value from the server directly into the observable.

<span data-bind="text: name"></span>

var viewModel = {
  name: ko.observable(<?php echo $data->name; ?>);
};

ko.applyBindings();

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.

<div data-bind="if: someFlag">
    <span data-bind="text: name">John Doe</span>
<div>

In the above example, everytime the someFlag value changes from false to true, the text binding on the span element will be re-initialised.

查看更多
时光不老,我们不散
3楼-- · 2019-08-07 03:15

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:

var defaultVm = {
    name: '<?php echo $data->name; ?>',
    anyVariable: '<?php echo $data->anyVariable; ?>'
}

Then you include this php file as a js file and init your viewmodel with it:

var viewModel = {
    name: ko.observable(defaultVm.name);
    anyVariable: ko.observable(defaultVm.anyVariable);
};
ko.applyBindings(viewModel); 

Solution 2: Use the ko.mapping plugin

Create a php file with:

{
    "name": "<?php echo $data->name; ?>",
    "anyVariable": "<?php echo $data->anyVariable; ?>"
}

Then in your js, you can use the ko.mapping plugin:

var viewModel = function (data) {
    ko.mapping.fromJS(data, {}, this);
};
ko.applyBindings(new viewModel(getYourPhpFileTheWayYoulike)); 

This allows you to get your data asynchronously (if you want) with something like:

$.getJSON("yourphpmodelurl", function (data) {
    ViewModelInstance = new viewModel(data);
    ko.applyBindings(ViewModelInstance);
}
查看更多
smile是对你的礼貌
4楼-- · 2019-08-07 03:16

You can create a custom binding handler to do this:

ko.bindingHandlers.textInitialized= {
    init: function (element, valueAccessor) {
        valueAccessor()(element.innerHTML); // get the current value and update the observable
    },
    update: function (element, valueAccessor) {
        var value = valueAccessor();
        element.innerHTML = ko.utils.unwrapObservable(value);
    }
};

And then you can bind to your viewmodel like this:

Name: <span data-bind="textInitialized: name" class="name">John B</span>

EDIT after jsFiddle:

You have created a completely different thing in the jsFiddle. A few things:

  1. Inside your autocomplethandler, you use the code I provided, but: you want to set the "value"-attribute, not the innerHTML, so you should change that to element.value instead of element.innerHTML.
  2. You have both an autocomplete-binding and a value-binding. Both of them work on the value-attribute (if you follow my first comment). The second one will come in after the first and undo that change.

I have modified the fiddle with these changes: http://jsfiddle.net/P8N77/24/

查看更多
登录 后发表回答