绑定问题与复杂数据和自动完成

时间:2014-12-02 17:07:00

标签: javascript jquery knockout.js

我正在使用Knockout JS 3.2,我想将它与自动完成下拉列表一起使用。我无法解决两个问题。

我简化了数据和代码,因此它可以独立运行:

<script type="text/javascript">
    var data = [
            { "User": { "Id": 1, "DisplayName": "john a" }, "Roles": [{ "Id": 1, "Name": "admins" }, { "Id": 2, "Name": "users" }] },
            { "User": { "Id": 2, "DisplayName": "john b" }, "Roles": [] },
            { "User": { "Id": 3, "DisplayName": "john c" }, "Roles": [{ "Id": 1, "Name": "admins" }] },
            { "User": { "Id": 4, "DisplayName": "john d" }, "Roles": [] },
            { "User": { "Id": 5, "DisplayName": "john e" }, "Roles": [{ "Id": 2, "Name": "users" }] }
    ];

    $(function () {
        $("#searchTerm").autocomplete({
            source: data,
            minLength: 1,
            select: function (event, ui) {
                if (ui.item) {
                    var viewModel = ko.mapping.fromJS(ui.item);
                    ko.cleanNode($("#userDetails")[0]);
                    ko.applyBindings(viewModel, $("#userDetails")[0]);
                }
            }
        })
        .autocomplete("instance")._renderItem = function (ul, item) {
            return $("<li>")
              .append("<a>" + item.User.DisplayName + "</a>")
              .appendTo(ul);
        };
    });
</script>


<div>Select User: <input id="searchTerm" name="searchTerm" type="text" /></div>

<div id="userDetails">
    <div>User: <span data-bind="text: User.DisplayName"></span></div>
    <div data-bind="foreach: Roles, visible: Roles().length > 0">
        <div><span data-bind="text: Name"></span></div>
    </div>
</div>

问题:

  1. 我想仅在绑定时显示userDetails div - 在页面加载时隐藏它。我尝试设置style="display:none",然后设置data-bind="if:User"data-bind="if:User.Id"。设置显示属性会在加载时隐藏元素,但在绑定时不会更改。

  2. 角色元素绑定无法正常工作。在第一次选择该用户时,角色显示,但在更改用户选择后无法显示。

1 个答案:

答案 0 :(得分:0)

您需要拥有一个具有selectedUser属性的正确视图模型,而不是始终重新绑定,而只需在automcomplete处理程序中更新该属性。

var viewModel = {
    selectedUser: ko.observable()
}

ko.applyBindings(viewModel, $("#userDetails")[0]);

$(function () {
    $("#searchTerm").autocomplete({
        source: data,
        minLength: 1,
        select: function (event, ui) {
            if (ui.item) {
                var user = ko.mapping.fromJS(ui.item);
                viewModel.selectedUser(user);                                       
            }
        }
    })
    .autocomplete("instance")._renderItem = function (ul, item) {
        return $("<li>")
          .append("<a>" + item.User.DisplayName + "</a>")
          .appendTo(ul);
    };
});

使用这种方法,您可以使用with binding,它也可以解决您的两个问题:

<div id="userDetails" data-bind="with: selectedUser">
    <div>User: <span data-bind="text: User.DisplayName"></span></div>
    <div data-bind="foreach: Roles, visible: Roles().length > 0">
        <div><span data-bind="text: Name"></span></div>
    </div>
</div>

演示JSFiddle