避免 Kendo Grid 搜索中的空值
我是 Telerik 的新手,目前正在使用 ASP.Net Core Grid
我已经可以正常工作了,但现在我想添加搜索栏工具栏,因此我将其添加为:
@(Html.Kendo().Grid(Model)
.Name("grid")
.ToolBar(t => t.Search())
.Search(s =>
{
s.Field(o => o.PrimaryContact.FirstName, "contains");
})
问题是
PrimaryContact.FirstName
可以为空,因此当我尝试搜索某些内容时,它会引发控制台错误:
Uncaught TypeError: Cannot read properties of null (reading 'FirstName')
同样的事情也发生在列上,我通过添加
ClientTemplate
解决了此问题,如下所示:
columns.Bound(x => x.PrimaryContact.FirstName)
.ClientTemplate("#= PrimaryContact ? PrimaryContact.FirstName : '' #")
但是搜索没有客户端模板来处理此问题
我尝试使用 jQuery 将字符串的空值更改为空如:
function onDataBound(e) {
for (let i = 0; i < rows.length; i++)
{
const row = $(rows[i]);
const dt = e.sender.dataItem(row);
const firstName = dt.get("PrimaryContact.FirstName");
if (firstName === null)
{
row[0].cells[2].innerHTML = "";
}
}
}
但是它不起作用。
如何避免搜索中的空值?问候
FullCode:
@(Html.Kendo().Grid(Model)
.Name("grid")
.ToolBar(t =>
{
t.Excel();
t.Pdf();
t.Search();
})
.DataSource(dataSource => dataSource
.Custom()
.PageSize(20)
.Schema(schema =>
{
schema.Data(x => "function(d) { return validateData(d); }");
})
)
.Pageable(pager => pager
.Numeric(true)
.Info(true)
.PreviousNext(true)
.PageSizes(new [] { 10 ,25 ,50 })
.Position(GridPagerPosition.Bottom)
.Messages(m =>
{
m.ItemsPerPage("entries");
m.Display("Showing {0} - {1} of {2} entries");
})
)
.Sortable()
.Search(s =>
{
s.Field(o => o.Name, "contains");
s.Field(o => o.PrimaryContact.FirstName, "contains");
s.Field(o => o.PrimaryContact.PhoneNumber, "contains");
s.Field(o => o.PrimaryContact.EmailAddress, "contains");
s.Field(o => o.IsActive, "contains");
})
.Events(events => events.DataBound("onDataBound"))
.Columns(columns =>
{
columns.Bound(x => x.AdvertiserId)
.Hidden();
columns.Bound(x => x.Name)
.Title("Advertiser Name");
columns.Bound(x => x.PrimaryContact.FirstName)
.ClientTemplate("#= PrimaryContact ? PrimaryContact.FirstName : '' #")
.Title("Contact Name");
columns.Bound(x => x.PrimaryContact.PhoneNumber)
.ClientTemplate("#= PrimaryContact ? PrimaryContact.PhoneNumber : '' #")
.Title("Contact Phone");
columns.Bound(x => x.PrimaryContact.EmailAddress)
.ClientTemplate("#= PrimaryContact ? PrimaryContact.EmailAddress : '' #")
.Title("Contact Email");
columns.Bound(x => x.IsActive)
.Title("Status")
.ClientTemplate("<span class='badgeTemplate'></span>")
.Sortable(false);
columns.Template("<div class='btn-group'></div>")
.Title("").Width(100);
})
)
<script type="text/javascript">
function validateData(data)
{
for (const item of data) {
if (!item.hasOwnProperty("PrimaryContact")) {
item["PrimaryContact.FirstName"] = { "FirstName": ""};
}
}
return data;
}
</script>
我也尝试使用
BeforeEdit 事件
.Events(events => events.DataBound("onDataBound").BeforeEdit("onBeforeEdit")
function onBeforeEdit(e) {
if(e.model.isNew()){
e.PrimaryContact.FirstName = "";
}
}
但是它不起作用
尽可能避免使用嵌套属性。您应该有一个自定义 ViewModel,它可以将所有内容(无论您的
Model
类是什么)扁平化。其次,asp.net API 的功能不如本机 javascript 库那么全面。无论如何,它只是在页面上生成 javascript 的通道,所以如果需要,不要害怕添加 javascript。
您尝试做的事情是不可能的。您可以构建一个适当的平面 ViewModel,或者您可以在将数据加载到网格之前拦截数据并进行变异。您可以使用数据源上的
schema
属性来执行此操作。您将定义一个自定义 javascript 方法。
还有一件事,我认为您的问题不是缺少
FirstName
,而是
PrimaryContact
为空。您可能可以毫不费力地修复此服务器端。但是,如果您从第三方 API 获取此信息,则以下是修复客户端的方法。
.DataSource(ds =>
{
ds
.Custom()
.Transport(t =>
{
// ...
})
.Schema(x => .Data(x => "function(d) { return validateData(d); }"))
// ...
;
})
或者,如果您只是使用 javascript 定义
dataSource: {
// ...
schema: { data: validateData }
}
然后,以下是使用 javascript 方法清理模型并修复您需要修复的任何属性:
function validateData(data)
{
for (const item of data) {
if (!item.hasOwnProperty("PrimaryContact")) {
item["PrimaryContact"] = { "FirstName": ""};
}
}
return data;
}
完整 dojo 示例在这里