循环渲染Kendo DropDownLists及数据过滤的问题排查
Kendo下拉框循环渲染问题解答
视图代码
@for (var i = 0; i < Model.ApprovingRoles.Count; i++) { <div class="col-lg-6"> @(Html.Kendo().DropDownListFor(m => m.ApprovingRoles[i]) .Size(ComponentSize.Medium) .Rounded(Rounded.Medium) .FillMode(FillMode.Outline) .OptionLabel("Select " + Model.ApprovingRoles[i].Name) .HtmlAttributes(new { style = "width: 100%", required = "required", validationmessage = "Value required" }) .DataTextField(nameof(SystemUserModel.EmployeeName)) .DataValueField(nameof(SystemUserModel.Id)) .Filter(FilterType.Contains) .DataSource(source => { source.Read(read => { read.Action("GetUsersByRoleId", "Api").Data(Model.ApprovingRoles[i].Id.ToString()); }).ServerFiltering(true); }) .Height(500) ) </div> }
疑问与当前现象
疑问
- 这种循环渲染下拉框的方式是否正确?
- 每个下拉框需通过GetUsersByRoleId API,以
m.ApprovingRoles[i].Id作为过滤条件,是否配置正确? read.Action().Data()的设置是否正确?
当前现象
- 正确显示4个下拉框
- 选项标签正确
- 下拉框无数据
- GetUsersByRoleId接口接收的int类型参数
roleId始终为0
问题解答
1. 循环渲染下拉框的方式是否正确?
循环渲染的逻辑本身没问题,但存在闭包陷阱风险——如果直接在循环中引用i,后续绑定的数据源或事件可能会引用循环结束后的i值。不过你当前下拉框数量显示正确,说明渲染阶段没有问题,数据源无数据的问题出在参数传递上。
2. API过滤条件配置是否正确?
逻辑方向是对的,但实现方式错误,导致接口接收的roleId始终为0。核心问题是Data()方法的使用方式不符合Kendo的要求:你直接传递了Model.ApprovingRoles[i].Id.ToString(),这会在视图渲染时把当前i对应的Id硬编码成字符串,但Kendo的Data()需要的是一个JavaScript函数,用来动态生成请求参数。
3. read.Action().Data()的设置是否正确?
完全错误。正确的用法是通过JavaScript函数动态传递参数,同时要避免闭包陷阱。
修复方案
方案一:局部变量捕获Id+匿名JS函数
在循环内创建局部变量捕获当前的roleId,避免闭包问题,同时传递返回参数的匿名JS函数:
@for (var i = 0; i < Model.ApprovingRoles.Count; i++) { // 捕获当前循环的roleId,避免闭包陷阱 var currentRoleId = Model.ApprovingRoles[i].Id; <div class="col-lg-6"> @(Html.Kendo().DropDownListFor(m => m.ApprovingRoles[i]) // 保留原有配置... .DataSource(source => { source.Read(read => { read.Action("GetUsersByRoleId", "Api") .Data($"function() {{ return {{ roleId: {currentRoleId} }}; }}"); }).ServerFiltering(true); }) // 保留原有配置... ) </div> }
方案二:HTML Data属性+全局JS函数
把roleId存储到下拉框的HTML Data属性中,通过全局JS函数读取并传递:
@for (var i = 0; i < Model.ApprovingRoles.Count; i++) { <div class="col-lg-6"> @(Html.Kendo().DropDownListFor(m => m.ApprovingRoles[i]) .HtmlAttributes(new { style = "width: 100%", required = "required", validationmessage = "Value required", data_role_id = Model.ApprovingRoles[i].Id // 存储roleId到Data属性 }) // 保留原有配置... .DataSource(source => { source.Read(read => { read.Action("GetUsersByRoleId", "Api") .Data("getDropdownRoleId"); // 指定全局JS函数名 }).ServerFiltering(true); }) // 保留原有配置... ) </div> } // 在视图底部添加全局JS函数 <script> function getDropdownRoleId() { // 获取当前触发请求的下拉框实例,读取Data属性 var dropdownElement = $(this); return { roleId: dropdownElement.data("role-id") }; } </script>
额外检查项
- 确认后端
GetUsersByRoleId接口的参数名是roleId,大小写完全匹配; - 直接通过浏览器地址栏测试接口:
/Api/GetUsersByRoleId?roleId=xxx(替换xxx为有效角色Id),确认能返回正确的用户列表。
内容的提问来源于stack exchange,提问作者DoomerDGR8
相关产品推荐
相关产品推荐

