项目选择使用KnockoutJS的MVC视图

时间:2014-04-25 06:40:30

标签: javascript jquery asp.net-mvc knockout.js

我正在尝试实现一个通用的ASP.net MVC视图。 UI应显示从服务器加载数据(基本上是字符串列表)的可用和选定项目的列表。用户可以对列表进行更改,即可以从可用项目列表中选择新项目,也可以从所选列表中删除项目。

我想使用KnockoutJS来利用绑定。

我设法完成所有工作,除了在可用列表中初始化视图时将所选项目显示为已选中。例如。 As Shown Here

我尝试了各种选项(using template (closest to what I want to achieve)Checked attrpossible options),问题是如果我设法显示项目检查了一些其他功能中断。尝试定义一个模板,但无法让它在我的情况下工作。

HTML:

<div class='moverBoxOuter'>
<div id='contactsList'>
    <span data-bind="visible: availableItems().length > 0">Available countries: </span>
    <ul data-bind="foreach: availableItems, visible: availableItems().length > 0">
        <li>
            <input type="checkbox" data-bind="checkedValue: $data, checked: $root.selectedItems" />
            <span data-bind="text: title"></span>
        </li> 
    </ul>

    <span data-bind="visible: selectedItems().length > 0">Selected countries: </span>

    <ul data-bind="foreach: selectedItems, visible: selectedItems().length > 0">
        <li>
            <span data-bind="text: title"></span>
            <a href="#" data-bind="click: $parent.removeItem">Delete</a>
        </li> 
    </ul>
</div>

JS:

    var initialData = [
    {
        availableItems: [
          { title: "US", isSelected: true },
          { title: "Canada", isSelected: false },
          { title: "India", isSelected: false }]
    },
    {
        selectedItems: [
          { "title": "US" },
          { "title": "Canada" }
        ]
    }
];

function Item(titleText, isSelected) {
    this.title = ko.observable(titleText);
    this.isSelected = ko.observable(isSelected);
}

var SelectableItemViewModel = function (items) {
    // Data
    var self = this;

    self.availableItems = ko.observableArray(ko.utils.arrayMap(items[0].availableItems, function (item) {
        return new Item(item.title, item.isSelected);
    }));

    self.selectedItems = ko.observableArray(ko.utils.arrayMap(items[1].selectedItems, function (item) {
        return new Item(item.title, item.isSelected);
    }));

    // Operations
    self.selectItem = function (item) {
        self.selectedItems.push(item);
        item.isSelected(!item.isSelected());
    };

    self.removeItem = function (removedItem) {
        self.selectedItems.remove(removedItem);
        $.each(self.availableItems, function (item) {
            if (item.title === removedItem.title) {
                item.isSelected = false;
            }
        });
    };
}

var vm = new SelectableItemViewModel(initialData);

$(document).ready(function () {
    ko.applyBindings(vm);
});

请你帮帮忙,请看下面的jsfiddle:

http://jsfiddle.net/sbirthare/KR4a6/6/

**更新:跟进以下问题**

其后续问题:

我需要在同一个用户界面上添加一个组合框,例如对于美国州。可用的项目是县,根据用户选择状态组合我需要过滤县。我使用AJAX从服务器获取数据并且所有成功但是显示的列表没有刷新。我期待正确的绑定设置,如果我们在viewmodel中更改observable数组,UI应该更改。我尝试强制更改为availableItems,但它只显示所有项目。请查看您是否可以在下面的代码中发现我正在更新ViewModel observable数组的问题。

function multiselect_change() {

            console.log("event: openmultiselect_change");

            var selectedState = $("#stateDropdownSelect").val();

            var propertyName = $("#PropertyName").val();
            var searchId = @Model.SearchId;
            var items;

            var model = { propertyName: propertyName, searchId: searchId, stateName: selectedState };
            $.ajax({
                url: '@Url.Action("GetFilterValues", "Search")',
                contentType: 'application/json; charset=utf-8',
                type: 'POST',
                dataType: 'html',
                data: JSON.stringify(model)
            })
                .success(function(result) {
                    debugger;

                    items = JSON.parse(result);

                    vm.availableItems(items.AvailableItems);

                    //vm.availableItems.valueHasMutated();

                    //var item = document.getElementById('availableItemId');
                    //ko.cleanNode(item);
                    //ko.applyBindings(vm, item);

                    vm.filter(selectedState);
                })
                .error(function(xhr, status) {
                    alert(status);
                });        
    }

2 个答案:

答案 0 :(得分:1)

正如user3426870所提到的,您需要将传递给检查绑定的值更改为boolean。

<input type="checkbox" data-bind="checkedValue: $data, checked: isSelected" />

另外,我认为您不需要在初始数据中使用selectedItems。

相反,在viewModel中,您可以执行以下操作:

self.selectedItems = ko.computed(function() {
            return ko.utils.arrayFilter(self.availableItems(), function (item) {
                return item.isSelected();
            });
        });

答案 1 :(得分:0)

这是因为您为绑定checked提供了一个数组,而它应该是一个与truefalse(如undefind或空字符串)相当的值。 我会使用函数检查$data是否在您的数组中,并为绑定返回一个布尔值。

类似的东西!