You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ajax更新Kendo MultiSelect数据源需触发额外服务请求才生效问题

问题根因

这个问题核心是Kendo MultiSelect的内部状态机制导致的:

  • 配置AutoBind(false)且页面加载阶段通过BindTo()绑定了初始值时,控件会缓存初始渲染的数据源状态,不会自动响应外部直接对dataSource.data()的替换操作
  • 原Ajax回调仅替换了数据集,没有触发控件视图重绘,也没有处理初始选中值和新数据源的匹配逻辑,所以界面不会更新
  • 用户手动输入触发GetMembersByMemberTypeIds的read请求后,控件会自动完成内部数据源状态初始化和视图重绘,后续替换数据才会正常生效
  • 原代码里的async: false同步Ajax已经被现代浏览器标记为废弃,会阻塞主线程造成页面卡顿,不建议使用。
可行解决方案

方案1:通过Kendo官方API规范更新数据源(推荐)

不要直接修改dataSource.data(),通过官方提供的setDataSource方法更新数据源,主动触发控件重绘,同时清理无效的初始选中值,不会产生冗余请求,修正后的代码如下:

function getPsychiatrists() {
    // 移除async:false,使用异步回调处理逻辑,避免阻塞UI
    $.ajax({
        url: "/CommonJsonActions/GetPsychiatrists",
        type: "GET",
        dataType: "json",
        success: function (result) {
            var multiSelect = $ddlExplainingPractitioner.data("kendoMultiSelect");
            // 格式化返回数据
            var resultData = $.map(result, function (v) {
                return { MemberId: v.MemberId, DisplayName: v.DisplayName };
            });

            // 清空原有无效选中值
            multiSelect.value([]);
            // 重新绑定数据源,无需重复设置TextField/ValueField,初始化阶段已经配置完成
            multiSelect.setDataSource(new kendo.data.DataSource({
                data: resultData
            }));
            // 触发控件重绘
            multiSelect.refresh();
        }
    })
}

如果更新数据源后需要保留新数据集中存在的原有选中值,可以在更新前暂存原value,过滤出有效值后重新赋值:

success: function(result) {
    var multiSelect = $ddlExplainingPractitioner.data("kendoMultiSelect");
    var oldValue = multiSelect.value(); // 暂存原有选中值
    var resultData = $.map(result, function (v) {
        return { MemberId: v.MemberId, DisplayName: v.DisplayName };
    });
    multiSelect.setDataSource(new kendo.data.DataSource({data: resultData}));
    // 过滤出存在于新数据源中的有效值,避免无效选中
    var validValue = $.grep(oldValue, function(val) {
        return resultData.some(function(item) { return item.MemberId == val; });
    });
    multiSelect.value(validValue);
    multiSelect.refresh();
}

方案2:模拟搜索行为触发控件初始化(临时兼容用,不推荐)

如果不想大幅修改原有逻辑,可以手动触发一次控件的搜索行为,提前完成内部状态初始化,需要注意你配置了MinLength(2),直接传空字符串无法触发搜索,需要临时调整配置:

success: function (result) {
    var ddlData = $ddlExplainingPractitioner.data("kendoMultiSelect");
    var resultData = [];
    $.each(result, function (k, v) {
        resultData.push({ MemberId: v.MemberId, DisplayName: v.DisplayName });
    });

    ddlData.dataTextField = "DisplayName";
    ddlData.dataValueField = "MemberId";
    // 临时取消最小输入长度限制,触发一次初始化请求
    ddlData.setOptions({minLength: 0});
    ddlData.search("");
    // 恢复原有最小输入长度配置
    ddlData.setOptions({minLength: 2});
    
    ddlData.dataSource.data(resultData);
    ddlData.refresh();
}

注意:该方案会额外发起一次GetMembersByMemberTypeIds请求,存在服务端资源浪费,仅作为临时兼容方案使用。

额外优化建议
  • 你给MultiSelect配置了MaxSelectedItems(1),本质是单选场景,直接使用Kendo DropDownList会比MultiSelect更轻量,也不会出现这类多选控件特有的状态同步问题
  • 移除Ajax请求中的async: false配置,同步请求会阻塞页面所有交互,用户体验极差
  • 不要在每次Ajax回调里重复设置dataTextField和dataValueField,这两个属性在控件初始化时配置一次即可,重复赋值可能引发不可预期的状态异常

内容的提问来源于stack exchange,提问作者joseph.c

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 00:36:20