【问题标题】:Kendo DropDownList issue using select() after setDataSource()在 setDataSource() 之后使用 select() 的 Kendo DropDownList 问题
【发布时间】:2023-02-10 07:58:38
【问题描述】:

我正在使用 ajax 形式的剑道下拉列表小部件。加载表单时,我需要初始化下拉列表,设置其数据源,并根据两个值(复合键)以编程方式设置选定的下拉项。但是,我的 ddAssignee.select(function()) 中的 return 语句不会执行,因此不会选择任何内容。我在调用 setDataSource() 后立即检查了 ddAssignee.dataSource.view() 的内容,它是空的,所以我假设这就是为什么什么都没有被选中的原因。但是,我有一个单独的按钮,用于在加载表单后选择下拉项(“Take It”按钮),效果很好。在设置导致 dataSource.view() 仍然为空的数据源之后,我只是想弄清楚缺少什么。

Kendo 下拉列表在 select() 文档中有这个: “如果小部件未绑定(例如 autoBind 设置为 false),选择方法将不会在继续选择和值设置之前预取数据(与值方法不同),并且不会选择任何项目。”

但是,将 autoBind 设置为 true 仍然不能解决问题。

我附加了:

  • 编辑表单的截图
  • 使用 ajax 表单编辑表单 html
  • InitAssigneeDropdown() 基本下拉初始化
  • GetAllAssigneesDataSource() 通过 kendo.data.DataSource 返回下拉列表的远程数据
  • onEditTask 函数(在单击按钮打开编辑表单时执行 - 发生问题的地方)
  • “Take It”按钮事件(其中 select(function()) 成功运行)

任何帮助是极大的赞赏。谢谢!

@model 模型.Tasking.TaskModel

@using (Ajax.BeginForm("SaveEditTask", "Tasking", null, new AjaxOptions()
{
    UpdateTargetId = "frmEditTask",
    InsertionMode = InsertionMode.Replace,
    OnSuccess = "taskingSaveSuccess"
}, new { id = "frmEditTask", autocomplete = "off" }))
{
    <div class="modal-header">
        <h5 class="modal-title" id="modalTitle">Edit Task</h5>
    </div>
    <div class="modal-body" style="max-height:70vh; overflow-y:auto">
        @Html.AntiForgeryToken()

        @Html.ValidationSummary(false, "", new { @class = "text-danger" })

        @Html.HiddenFor(m => m.ID)
        @Html.HiddenFor(m => m.PtOID)
        @Html.HiddenFor(m => m.PtMRN)
        @Html.HiddenFor(m => m.CreatedByUserFK)
        @Html.HiddenFor(m => m.CreatedDTTM)

        <div class="form-group">
            @Html.LabelFor(m => m.PtFullName, new { @class = "text-dark font-weight-bold" })
            @Html.TextBoxFor(m => m.PtFullName, new { @class = "form-control mb-2", @readonly = "readonly" })
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.TypeFK, new { @class = "text-dark font-weight-bold" })
            @Html.DropDownListFor(m => m.TypeFK, (IList<SelectListItem>)ViewBag.TaskTypeOptions, new { @class = "form-control p-1 w-auto mb-2", @disabled = "disabled", @readonly = "readonly" })
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.StatusFK, new { @class = "text-dark font-weight-bold" })
            <br />
            @Html.DropDownListFor(m => m.StatusFK, (IList<SelectListItem>)ViewBag.TaskStatusOptions, new { @id = "ddTaskStatusType", @class = "form-control p-1 w-auto mb-2" })
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.PriorityFK, new { @class = "text-dark font-weight-bold" })
            <br />
            @Html.DropDownListFor(m => m.PriorityFK, (IList<SelectListItem>)ViewBag.TaskPriorityOptions, new { @id = "ddTaskPriorityType", @class = "form-control p-1 w-auto mb-2", data_default_due_date_url = Url.Action("GetDefaultDueDate", "Tasking", new { area = "" }) })
        </div>

        <div class="form-group">
            @Html.LabelFor(m => m.DueDTTM, new { @class = "text-dark font-weight-bold" })
            @if (Model.CreatedByUserFK == User.Identity.GetUserId())
            {
                @(Html.Kendo().DateTimePickerFor(m => m.DueDTTM).HtmlAttributes(new { @id="dtpTaskDueDate", data_toggle = "tooltip", data_placement = "bottom", data_trigger = "focus", required = "required" }))
            }
            else
            {
                @Html.TextBoxFor(m => m.DueDTTM, new { @class = "form-control mb-2", @readonly = "readonly" })
            }
        </div>

        <div class="form-group">
            @Html.LabelFor(m => m.AssigneeFK, new { @class = "text-dark font-weight-bold" })
            <br />
            <div class="row">
                <div class="col-9 pr-0">
                    <select id="ddTaskAssignee" name="AssigneeFK" data-all-assignees-url="@Url.Action("GetAllTaskAssigneeOptions", "Tasking", new { area = "" })" />
                </div>
                <div class="col-3 pl-2">
                    <button id="btnSelfAssignTask" type="button" class="btn btn-secondary" data-user-id-url="@Url.Action("GetUserId", "Tasking", new { area = "" })">Take It</button>
                </div>
            </div>
            @Html.HiddenFor(m => m.AssigneeTypeFK, new { @id = "hiddenAssigneeTypeFK" })
        </div>

        <div class="form-group">
            @Html.LabelFor(m => m.Description, new { @class = "text-dark font-weight-bold" })
            @if (Model.CreatedByUserFK == User.Identity.GetUserId())
            {
                @Html.TextAreaFor(m => m.Description, new { @class = "form-control" })
            }
            else
            {
                @Html.TextAreaFor(m => m.Description, new { @class = "form-control", @readonly = "readonly" })
            }
        </div>

    </div>

    <div class="modal-footer">
        @if (Model.CreatedByUserFK == User.Identity.GetUserId())
        {
            <button id="btnDeleteTask" type="button" class="btn btn-danger" data-target-url="@Url.Action("DeleteTask", "Tasking", new { area = "" })">Delete Task</button>
        }
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
        <button type="submit" class="btn btn-primary">Save</button>
    </div>
}
function initAssigneeDropDown() {
$("#ddTaskAssignee").kendoDropDownList({
    optionLabel: 'Select Assignee ...',
    filter: "contains",
    dataTextField: 'AssigneeName',
    dataValueField: 'AssigneeFK',
    template: function (dataItem) {
        //TODO - improve logic
        if (dataItem.AssigneeTypeFK == 1)
            return '<span><i class="fas fa-user pr-2"></i>' + dataItem.AssigneeName + '</span>';
        else if (dataItem.AssigneeTypeFK == 2)
            return '<span><i class="fas fa-users pr-2"></i>' + dataItem.AssigneeName + '</span>';
    }
});

}

function getAllAssigneesDataSource() {
var url = $('#ddTaskAssignee').data('all-assignees-url');

var dataSource = new kendo.data.DataSource({
    transport: {
        read: {
            type: "POST",
            url: url
        }
    }
});

return dataSource;

}

function onEditTask(e) {
//Fetch the ID, assigneeTypeFK, and assigneeFK from the grid item that's getting edited
var grid = $('#taskGrid').data('kendoGrid');
var taskDataItem = grid.dataItem($(e).closest("tr"));
var taskId = taskDataItem.ID;
var assigneeTypeFK = taskDataItem.AssigneeTypeFK;
var assigneeFK = taskDataItem.AssigneeFK; 

$('#taskModal').modal('show'); //Show the edit modal

$('#taskModal .modal-content').html(''); //Clear out the modal container

//ajax to return partial view for editing task
$.ajax({
    url: $(e).data("target-url"), 
    type: "POST",
    cache: false,
    data: JSON.stringify({ taskId: taskId }), //Pass the task id to controller
    contentType: "application/json; charset=utf-8",
    success: function (response) {
        $('#taskModal .modal-content').replaceWith(response); //add edit view html to modal

        initAssigneeDropDown();
        var ddAssignee = $('#ddTaskAssignee').data('kendoDropDownList');
        ddAssignee.setDataSource(dataSource);
        var assigneeDataSourceView = ddAssignee.dataSource.view(); //Issue - this is empty so select (below) will not work

        ddAssignee.select(function (dataItem) {
            return dataItem.AssigneeTypeFK == assigneeTypeFK && dataItem.AssigneeFK == assigneeFK;
        });

    },
    error: function (jqXHR, exception) {
        if (jqXHR.statusText !== 'abort') {
            // Our error logic here
            $('#kNotification').data('kendoNotification').error("An error occurred while loading the page.");
        }
    }
});

}

$('#taskModal').on('click', '#btnSelfAssignTask', function (e) {

//Ajax to return the current user's ID from the controller
$.ajax({
    url: $(e.currentTarget).data("user-id-url"),
    type: "POST",
    cache: false,
    contentType: "application/json; charset=utf-8",
    success: function (response) {
        var userId = response;

        //Set the value of the dropdown based on the user's id
        var ddAssignee = $('#ddTaskAssignee').data('kendoDropDownList');
        var assigneeDataSource = ddAssignee.dataSource.view(); //For testing
        //TODO improve logic
        ddAssignee.select(function (dataItem) {
            return dataItem.AssigneeTypeFK == 1 && dataItem.AssigneeFK == userId;
        });
    },
    error: function (jqXHR, exception) {
        if (jqXHR.statusText !== 'abort') {
            $('#kNotification').data('kendoNotification').error("An error occurred while assigning task");
        }
    }
});

});

【问题讨论】:

    标签: jquery kendo-ui kendo-dropdown


    【解决方案1】:

    这仍然适用:“如果小部件未绑定(例如 autoBind 设置为 false),选择方法将不会在继续选择和值设置之前预取数据(与值方法不同),并且不会有项目选中。”

    将 autoBind 设置为 true,数据源将在调用 setDataSource() 时立即调用服务器:

    ddAssignee.setDataSource(dataSource);
    

    但是它是异步执行的,您的代码同时继续执行。响应尚未返回,小部件尚未绑定,因此 datasource.view() 也未填充。这就是 select() 不起作用的原因。 “Take It”按钮有效,因为在使用时小部件已经绑定。

    您可以通过在 setTimeout 中调用 select() 来证明我是否正确:

    setTimeout(function () {
        ddAssignee.select(function (dataItem) {
            return dataItem.AssigneeTypeFK == assigneeTypeFK && dataItem.AssigneeFK == assigneeFK;
        });
    }, 5000);  // Assuming 5 seconds is long enough
    

    当然,这是实际解决此问题的一种可怕且不可靠的方法。最好的方法是在下拉列表中使用 dataBound 事件。当它触发时,您知道小部件已绑定,然后您可以以编程方式选择一个值。

    https://docs.telerik.com/kendo-ui/api/javascript/ui/dropdownlist/events/databound

    或者考虑您是否可以使用 value() 而不是 select(),因为它会在继续执行代码之前等待数据被获取和绑定。

    【讨论】:

      猜你喜欢
      • 2014-12-24
      • 1970-01-01
      • 1970-01-01
      • 2014-07-18
      • 2013-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-31
      相关资源
      最近更新 更多