selected object pattern with knockout

2019-05-25 08:11发布

Does anybody know how I'd accomplish the following pattern with knockoutJS? I use this pattern all the time in apache flex and want to see if I can mimic it. I am unsure how to replace an observable with another. Any help/thoughts much appreciated.

//model

myViewModel = {
 items : ko.observableArray(),
 selected_item : ko.observable()
 }

//view

<h3 data-bind="text : myViewModel.selected_item.name"> </h3>
<ul>
<!-- ko foreach: myViewModel.items -->
<li  data-bind="text : name"/>
<!-- /ko -->
</ul>

//logic

$('li').click(function(e){
    //check ko.dataFor(this) has different id from that of myViewModel.selected_item
    //if id different
    //set myViewModel.selected_item to ko.dataFor(this)
    //rejoice as h3 text changes
 })

标签: knockout.js
1条回答
霸刀☆藐视天下
2楼-- · 2019-05-25 08:58

You are on the right track. There are a few patterns that you can use to choose a selected item. If you want to attach a click handler unobtrusively, as you have above, then your best bet would be to use a delegated handler, so that you are set to handle changes to your observableArray. A delegated handler will be able to handle new elements being added.

So, you could do something like:

$("#content").on("click", "li", function(e) {
    var item = ko.dataFor(this),
        current = myViewModel.selected_item;

    if (!current() || item.id !== current().id) {
        current(item);
    }
});

Here is a sample: http://jsfiddle.net/rniemeyer/hBUBN/

When you bind to your h3, since selected_item can be null you would need to protect yourself by wrapping it in a with block (in the example), calling a function that handles null, or doing it in the binding like (data-bind="text: myViewModel.selected_item() ? myViewModel.selected_item().id : 'unknown'"). To keep it clean, this logic can be put in a function and you can call the function from your data-bind or using with prevents this from being an issue (although it renders nothing when it is null).

Otherwise, you can even just do this:

<!-- ko foreach: myViewModel.items -->
    <li  data-bind="text : name, click: $parent.selected_item"></li>
<!-- /ko -->

The click (and event) binding in KO 2.0 pass the current data as the first argument. You can use the $parent variable to access one scope level up (or $root to get to the base level). Observables are functions and you set their value by passing the new value as the first argument. So, doing $parent.selected_item here will call the observable function passing your data as the first argument. So, it will set your selected value to the proper item.

Sample: http://jsfiddle.net/rniemeyer/gemug/

查看更多
登录 后发表回答