【问题标题】:Binding a Kendo control to an HtmlHelper control using JavaScript and MVC / Razor使用 JavaScript 和 MVC / Razor 将 Kendo 控件绑定到 HtmlHelper 控件
【发布时间】:2014-09-20 15:42:30
【问题描述】:

我有一个 MVC ListBoxFor 控件,我正在尝试将数据绑定到并使用 Kendo MultiSelectFor 进行更新。

这个想法是在 ListBox 中有一个用户列表,在 MultiSelect 框中有一个可用用户列表。当从 MultiSelect 框中选择用户并单击添加按钮时,将对更新用户列表服务器端的操作进行 Ajax 调用(通过各种 API 调用,一切正常),客户端 JavaScript 用于更新用户和可用的用户数组对象和绑定使控件与更新的列表保持同步。

我希望我能把它归结为一个问题,但老实说,每次我尝试一些东西时都会遇到不同的错误,所以我会选择最新的迭代。

型号:

public IEnumerable<UserInformation> Users { get; set; }
public IEnumerable<UserInformation> AvailableUsers { get; set; }

JavaScript 视图模型:

var viewModel = kendo.observable({
        availableUsersSelected: [],
        users: @(Html.Raw(Json.Encode(this.Model.Users))),
        availableUsers: @(Html.Raw(JsonConvert.SerializeObject(this.Model.AvailableUsers))),
        moveToUsers: function () {
            this.availableUsersSelected = this.get('availableUsersSelected');

            this.users.push(this.availableUsers);

            if (this.availableUsersSelected.length > 0) {
                var formAction = '@Url.Combine(Url.Content("~/"), ControllerActions.Groups.GroupDefault, ControllerActions.Groups.AddUser)';
                $.ajax({
                    url: formAction,
                    type: 'POST',
                    data: {
                        model: JSON.stringify(
                            {
                                groupId: $('#GroupId').val(),
                                users: this.availableUsersSelected
                            }
                    )
                    },
                    success: function (result) {
                        if (result) {
                            this.users.remove(this.availableUsersSelected);
                        }
                    }
                });
            }
        }
    });

MultiSelectFor 控件

@(Html.Kendo()
    .MultiSelectFor(u => u.AvailableUsers)
    .Placeholder("Please select")
    .BindTo(new SelectList(Model.AvailableUsers, "Id", "Name"))
    .HtmlAttributes(new { data_bind = "value: availableUsersSelected" })
)

列表框控件

@(Html.EditorLine(Language.Fields.Users, Html.ListBoxFor(u => u.Users, new SelectList(Model.Users, "Id", "Name"), new { @class = "form-control", data_bind = "source: users", data_value_field ="Id", data_text_field = "Name" })))

添加控件

<img src="~/Content/images/up-arrow.jpg" alt="Move to users" width="30" data-bind="events: {click: moveToUsers}" />

重申一下,Ajax 调用和更新服务器端都可以正常工作,这是我难以理解的客户端控件绑定。

我遇到的错误是 1) 在此行 users: @(Html.Raw(Json.Encode(this.Model.Users))), 及其后的行(实际上是同一件事)上的逗号语法错误,以及 2) 上的“ReferenceError: Id is not defined”按下添加按钮时调用 moveToUsers 函数。

(老实说,我在这方面所经历的挫败感让我发疯了,如果问题中出现了,我很抱歉)

【问题讨论】:

  • 您好,目前在您的多选初始化中,您尚未指定导致绑定问题的 DataTextFieldDataValueField。关于列表,您不需要同时指定 data_bind="source: users" 和 BindTo。
  • 好的,我和你一起在 MultiSelect 上,我已经在 DataTextField 和 DataValueField 中添加了,但是对于列表,我是否应该在 JavaScript 中填充用户对象然后绑定到该对象而不是到 MVC 模型对象?
  • 尝试将您的列表代码更改为 @Html.ListBox(u => u.Users, new SelectList(Model.Users, "Id", "Name"), new { @class= "form-control", data_value_field ="Id", data_text_field = "Name" })) 另外,如果您不需要 EditorLine 控件,最好将其删除并直接使用上述代码。如果您没有将 Listbox 与模型中的任何变量绑定,那么最好使用 Listbox 而不是 ListobxFor。在您的情况下,我建议使用 ListBox 和 MultiSelect 而不是 ListBoxFor 和 MultiSelectFor。
  • 试过了,现在我在“this.users.remove(this.availableUsersSelected)”行收到“无法读取未定义的属性'删除'”错误。 EditorLine 控件是一种自定义扩展方法,它只是将传递给它的控件正确嵌入到页面布局中(让我不必重复重新键入相同的 div / 类结构)。
  • 好的,应该是“this.availableUsers.remove(this.availableUsersSelected)”,它消除了错误,但不会更新 MultiSelect 或 ListBox

标签: javascript asp.net-mvc razor data-binding kendo-ui


【解决方案1】:

如果您希望将数据删除或添加到 Kendo Multiselect,那么您需要通过 DataSource 将它们添加为:

$("#AvailableUsers").data("kendoMultiSelect").dataSource.add({"text": "new Item", "value": 1000});

有关向多选 (Kendo DataSrouce) 添加或删除项目的更多详细信息,请参阅:Kendo DataSource Adding Removing Items

同样,您可以从列表框中删除项目,如下所示:

        var selectedIndex = ListBox1.selectedIndex();
        clearSelection();

        if (selectedIndex != -1) {
            ListBox1.options.remove(selectedIndex);

有关在 HTML 列表框中添加或删除项目的更多详细信息,请参阅:HTML Listbox Items Manipulation.

如果您在此之后有任何错误,请告诉我。

【讨论】:

  • 非常感谢您的帮助,但我试图使用 Kendo 的数据绑定/可观察的 gubbins 来使其工作,而不是手动向控件添加项目,请参阅下面/上面的答案(无论它出现在哪里)
【解决方案2】:

所以在冷静下来之后,又阅读了一些关于数据绑定和可观察数组的文档,我意识到我犯了一些基本错误。

JavaScript 视图模型:

var viewModel = {
        availableUsersSelected: new kendo.data.ObservableArray([]),
        users: new kendo.data.ObservableArray(@(Html.Raw(Json.Encode(this.Model.Users)))),
        availableUsers: new kendo.data.ObservableArray(@(Html.Raw(Json.Encode(this.Model.AvailableUsers)))),
        moveToUsers: function () {
            if (viewModel.availableUsersSelected.length > 0) {
                var formAction = '@Url.Combine(Url.Content("~/"), ControllerActions.Groups.GroupDefault, ControllerActions.Groups.AddUser)';
                $.ajax({
                    url: formAction,
                    type: 'POST',
                    data: {
                        model: JSON.stringify(
                            {
                                groupId: $('#GroupId').val(),
                                users: viewModel.availableUsersSelected
                            }
                    )
                    },
                    success: function (result) {
                        if (result) {
                            removeFromAvailableUsers();
                        }
                        else
                            alert('add failed!');
                    },
                    failure: function () {
                        alert('ajax failed!');
                    }
                });
            }
        }
    };

function removeFromAvailableUsers() {
    for (var i = 0; i < viewModel.availableUsersSelected.length; ++i) {
        viewModel.users.push(viewModel.availableUsersSelected[i]);
        viewModel.availableUsers.remove(viewModel.availableUsersSelected[i]);
    }
    var ele = $('#AvailableUsers').data("kendoMultiSelect");
    ele.value("");
    ele.input.blur();
};

主要区别不是将整个对象声明为 kendo 可观察对象,而是将每个数组声明为可观察数组,然后通过 viewModel 对象引用它们,而不是假设“this”范围将封装它们。

然后,正如上面 cmets 中提到的 D_Learning 一样,我不必要地为 MultiSelect 控件使用了两个绑定,因此变成了:

    @(Html.Kendo()
        .MultiSelectFor(u => u.AvailableUsers)
        .Placeholder("Please select")
        .HtmlAttributes(new { data_bind = "source: availableUsers, value: availableUsersSelected", data_value_field = "Id", data_text_field = "Name" })
    )

(注意没有“.BindTo”属性)

除此之外,MVC 方面的内容保持不变,而且一切都完美无缺。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-28
    • 2012-07-09
    • 1970-01-01
    相关资源
    最近更新 更多