knockout observablearray in 2 templates

余生长醉 提交于 2019-12-25 08:16:58

问题


I have 2 observabeleArrays. One contains all the possible types which I can select and the other one contains all the selected ones. The first template shows all the possible types and the other all the selected ones. If I click on one of first template(all possibilities), it gets added to the list of selected ones and is displayed in the second template. If I click on a selected one in the second template it is removed from there. Also, in the first template I want to display a check on the objects that are selected. Most of the stuff works, except the check does not get updated if I remove an object via the second template. I've tried to reduce my code to the important parts, I hope it makes more sense like this and doesn't have any mistakes: Anyone an idea how to fix it, so my check shows correctly? It's depending on the Selected value of each object, which updates correctly, but the view doesn't change.

//main html
//...
            <div data-bind="component: {
                    name: 'selector-component',
                    params: {
                        selected: vm.selected,
                        types: vm.types,
                    }
                }">
            </div>
            <div data-bind="component: {
                    name: 'selected-component',
                    params: {
                        selected: vm.selected,
                    }
                }">
            </div>
//...
<script type="text/javascript">

    vm.selected = ko.observableArray([]);
    vm.types = ko.observableArray([]);

        ko.components.register('model-selected-component', {
            template: { element: document.getElementById('selector-component-template') },
            viewModel: SelectorComponentModel
        });
</script>
<script type="text/javascript">

    vm.selected = ko.observableArray([]);

        ko.components.register('model-selected-component', {
            template: { element: document.getElementById('selected-component-template') },
            viewModel: SelectorComponentModel
        });
</script>           

//template1
<template id="selector-component-template">
                    <div class="panelContainer">
                        <!-- ko foreach: types -->
                                <a data-bind="attr: {title: Name}, click: $parents.select" class="thumbnail text-center" href="#">
                                    <span style="display:block;height:10px;width:10px;">
                                        <i data-bind="visible: Selected" class="fa fa-check" style="color:green"></i>
                                     <img src="@Url.Content("~/Content/Images/type.png")" />
                                   </span>
                                </a>
                        <!-- /ko -->
                    </div>
</template>


//template2
<template id="selected-component-template">
    <div class="panel panel-default">
        <div class="panel-heading">Selected Properties</div>
        <div class="panel-body">
            <div class="panel-body panel-body-nobottompadding">
                <div class="panelContainer">
                    <!-- ko foreach: selected -->
                        <a class="thumbnail text-center" data-bind="attr: {title: Name}, click: $parent.select">
                            <img src="@Url.Content("~/Content/Images/type.png")" />
                        </a>
                    <!-- /ko -->
            </div>
        </div>
    </div>
</template>

//selector.js
function SelectorComponentModel(params) {

    var self = this;
    self.selected = params.selected || ko.observableArray([]);
    self.types = params.types || ko.observableArray([]);

    self.select = function (types) {
        if (self.selected.indexOf(types) == -1)
            self.selected.push(types);
        else
            self.selected.remove(types);

        types.Selected = types.Selected == true ? false : true;
        //refresh
        var data = self.types();
        self.types([]);
        self.types(data);
    }

回答1:


You should not try to maintain two separate arrays. Just make one array for all items and computed array for selected items only.

self.items = ko.observableArray();

self.items.selected = ko.computed(() => {
    return self.items().filter(item => item.selected());
});

Take a look at this example.

Update

As you may see I use arrow functions alot. However they are part of ES6 standard supported by most modern browsers your experience may differ. For such unlucky users there is more classic example.

Update 2

Of course your Selected property must be observable. You can convert this property for each item before assigning to the model.

Updated example



来源:https://stackoverflow.com/questions/41161828/knockout-observablearray-in-2-templates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!