Kendo ListView:Add/Create 在刷新浏览器会话之前不会反映出来
Kendo ListView: Add/Create not reflected until browser session is refreshed
我正在使用 MVC 和 Kendo (UI v2018.3.1017) ListView 来管理我称为 'MaximoList' 的列表。为了使列表对多个控制器可用,我利用了 MVC 提供的“TempData”对象。在创建(和销毁)时,我看到 MaximoList 对象正确反映了更改。但是为了反映 UI 中的变化,我必须刷新 (F5) (Chrome) 浏览器。
对控件的 CSHTML 引用相当简单:
<div class="col-md-3">
<div class="form-group">
<label style="white-space: nowrap;">Maximo Id's</label>
<a id="btnAddMaximoEntry" onclick=window.allIsos.addMaximoEntry() href="#" title='Add Maximo' style='margin-left: 8px'><i class='fa fa-upload'></i></a>
<div class="" id="divMaximoList">
</div>
</div>
</div>
控件的JS定义是:
function addMaximoListView(isoId, outageId) {
maximoListDataSource = new kendo.data.DataSource({
transport: {
read: { url: "/request/GetMaximoList", type: "GET", dataType: "json", cache: false },
create: { url: "/request/AddMaximoEntry", type: "Post", dataType: "json", cache: false },
destroy: { url: "/request/DeleteMaximoEntry", type: "POST", dataType: "json", cache: false },
update: {},
parameterMap: function (data, type) {
if (type == "read") { return { IsoId: isoId, OutageId: outageId }; }
if (type == "create") { return { MaximoId: data.MaximoId }; }
if (type == "destroy") { return { id: data.Id }; }
},
sortable: true,
pageable: true,
},
requestEnd: function (e) {
console.log(e.type);
console.log(e.response);
},
columns: [
{ field: "Id", Title: "Id", width: "0px" },
{ field: "MaximoId", Title: "MaximoId", width: "50px" },
{ command: ["edit", "destroy"], title: " ", width: "250px" }
],
autoSync: false,
schema: {
model: {
id: "Id",
fields: {
Id: { editable: false },
MaximoId: { editable: true, type: "string" },
}
},
},
});
var getTemplate = ""
+ "<div>"
+ " <a onclick=window.allIsos.deleteMaximo(#:Id#) href='\#'><i class='fa fa-trash'></i></a>"
+ '#:MaximoId#</div>';
var editTemplate = ""
+ "<div>"
+ " <input type='text' data-bind='value: MaximoId' name='MaximoId' required='required' />"
+ " <div>"
+ " <a class='k-button k-update-button' href='\#'><span class='k-icon k-i-check'></span></a>"
+ " <a class='k-button k-cancel-button' href='\#'><span class='k-icon k-i-cancel'></span></a>"
+ " </div>"
+ "</div>";
$("#divMaximoList").kendoListView({
template: kendo.template(getTemplate),
editTemplate: kendo.template(editTemplate),
dataSource: maximoListDataSource,
pageSize: 5,
dataBound: function (e) {
console.log("ListView is bound and ready to render.");
}
});
};
将项目添加到列表的 JS 定义是:
var addMaximoEntry = function () {
var listView = $("#divMaximoList").data("kendoListView");
listView.add();
};
正在重新启动调试本地应用程序,这里是公开来自 API/Database:
的测试数据的控件
我点击了我的添加按钮,在接受条目之前,请注意我的新 MaximoId 的输入值 'NotWorking':
接受输入后,请注意控件添加了一个新条目,但它是原始项目之一的幽灵:
但是在刷新页面 (F5) 后,请注意当 GET 触发从服务器端 TempData 对象拉取时,实际的 'NotWorking' 项目已被服务器正确接收,并且更新的 TempData 对象被传递给UI(包括新条目):
Create/Add 的 API 方法如下 - 我返回到 UI,更新后的 MaximoList 对象的 JSON 表示并使用它更新对象,刷新到 TempData["MaximoList"]:
[HttpPost, Route("AddMaximoEntry")]
public ActionResult AddMaximoEntry(string MaximoId)
{
var ignoreCase = StringComparison.InvariantCultureIgnoreCase;
try
{
List<MaximoEntry> maximoList = TempData["MaximoList"] != null ? TempData["MaximoList"] as List<MaximoEntry> : new List<MaximoEntry>();
var maximoId = MaximoId;// unnecessary variable, but used for testing against multiple method confgurations
var maximoEntry = new MaximoEntry();
maximoEntry.MaximoId = maximoId;
if (maximoList.Where(s => s.MaximoId.Equals(maximoEntry.MaximoId, ignoreCase)).FirstOrDefault() == null)
maximoList.Add(maximoEntry);
TempData["MaximoList"] = maximoList as List<MaximoEntry>;
return Json(maximoList, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
return new JsonResult
{
Data = new
{
id = 0,
Success = false,
Msg = "Something went wrong while adding to the Maximo List. Please contact system support!"
}
};
}
}
而 API GET 如下:
[HttpGet, Route("GetMaximoList")]
public ActionResult GetMaximoList(int IsoId, int OutageId)
{
try
{
List<MaximoEntry> maximoList = ODataGetMaximoList(IsoId, OutageId);
return Json(maximoList, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
return new JsonResult
{
Data = new
{
id = 0,
Success = false,
Msg = "Something went wrong while getting Maximo List. Please contact system support!"
}
};
}
}
最初,ADD(CREATE) 的 API 方法传回了 Maximo 条目的整个列表(JSON 数组)。
解决方案是仅传回最初传递给 ADD(CREATE) 方法的 model 对象的更新版本,包括新分配的“id”值。新创建的条目将有一个负索引值,稍后我将在 MERGE 语句中的数据库级别使用它(即主键的负值不应该存在于数据库中table)来同步数据库。
如果还不清楚,我正在使用 TempData["MaximoList"] 对象来维护跨 API 控制器的 Kendo ListView 控件的状态。将控件状态保存到 DB(利用 TempData 对象)将发生在更通用的控制器方法中,该方法不管理 TempData 对象的状态(adds/deletes/etc。)。
我还重新设计了 DESTROY(删除)组件以仅在成功的 API 调用时从 (UI) 列表中删除已删除的项目,并通过删除一个清理了 JS不需要反映 TempData 对象状态的控件的不必要集数。
我的 API ADD 方法现在是:
[HttpPost, Route("AddMaximoEntry")]
public JsonResult AddMaximoEntry(MaximoEntry model)
{
var ignoreCase = StringComparison.InvariantCultureIgnoreCase;
try
{
List<MaximoEntry> maximoList = TempData["MaximoList"] != null ? TempData["MaximoList"] as List<MaximoEntry> : new List<MaximoEntry>();
var minId = maximoList.Where(w => w.id <= 0);
model.id = minId.Count() == 0 ? -1 : minId.Select(s => s.id).Min() - 1;
if (maximoList.Where(s => s.maximoId.Equals(model.maximoId, ignoreCase)).FirstOrDefault() == null)
maximoList.Add(model);
TempData["MaximoList"] = maximoList as List<MaximoEntry>;
return Json(model, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
return new JsonResult
{
Data = new
{
Success = false,
Msg = "Something went wrong while adding to the Maximo List. Please contact system support!"
}
};
}
}
我还更新了我的 DELETE 方法,作为 HTTPDELETE 方法,并返回一个状态指示器来提醒调用 JS 操作结果:
[HttpDelete, Route("DeleteMaximoEntry")]
public JsonResult DeleteMaximoEntry(int id)
{
try
{
List<MaximoEntry> maximoList = TempData["MaximoList"] != null ? TempData["MaximoList"] as List<MaximoEntry> : new List<MaximoEntry>();
var itemToRemove = maximoList.SingleOrDefault(r => r.id == id);
if (itemToRemove != null)
maximoList.Remove(itemToRemove);
TempData["MaximoList"] = maximoList as List<MaximoEntry>;
return Json(new { success = true, responseText = $"id {id} deleted from TempData object" });
}
catch (Exception ex)
{
var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
return new JsonResult
{
Data = new
{
Success = false,
Msg = $"Something went wrong while deleteing Maximo Entry (id {id}). Please contact system support!"
}
};
}
}
SELECT (READ) 和 CREATE(Add) 的 JS 控件定义是:
function addMaximoListView(isoId, outageId) {
maximoListDataSource = new kendo.data.DataSource({
transport: {
batch: false,//default is false
read: { dataType: "json", cache: false, type: "GET", url: "/request/GetMaximoList" },
create: { dataType: "json", cache: false, type: "POST", url: "/request/AddMaximoEntry" },
parameterMap: function (data, type) {
if (type == "read") { return { IsoId: isoId, OutageId: outageId }; }
if (type == "create") { return { model: data }; }
},
},
requestEnd: function (e) {
console.log(e.type);
console.log(e.response);
},
autoSync: false,
serverFiltering: true,
schema: {
model: {
id: "id",
fields: {
maximoId: { editable: true, type: "string" },
}
},
},
});
var getTemplate = ""
+ "<div>"
+ " <a onclick=window.allIsos.deleteMaximo(#:id#) href='\#'><i class='fa fa-trash'></i></a>"
+ " #:maximoId#"
+ "</div > ";
var editTemplate = ""
+ "<div>"
+ " <input type='text' data-bind='value: maximoId' name='MaximoId' required='required' />"
+ " <div>"
+ " <a class='k-button k-update-button' href='\#'><span class='k-icon k-i-check'></span></a>"
+ " <a class='k-button k-cancel-button' href='\#'><span class='k-icon k-i-cancel'></span></a>"
+ " </div>"
+ "</div>";
$("#divMaximoList").kendoListView({
template: kendo.template(getTemplate),
editTemplate: kendo.template(editTemplate),
dataSource: maximoListDataSource,
dataBound: function (e) {
console.log("ListView is bound and ready to render.");
}
});
};
对于DESTROY(DELETE),我添加了这些JS方法(希望将这些元素嵌入到控件定义中):
var deleteMaximo = function (id) {
executeDeleteMaximo(id, "Are you sure you want to delete this Maximo entry?");
}
function executeDeleteMaximo(id, confirmMsg) {
common.LoadingGif("#mainView", false);
common.ConfirmDialog(true, confirmMsg,
function (reason) {
if (reason == "NO") {
common.LoadingGif("#mainView", true);
return false;
}
$.ajax({
type: "DELETE",
data: { id: id },
url: "/request/DeleteMaximoEntry",
success: function (response) {
var data = response;
if (data.success) {
var myDataSource = $("#divMaximoList").data().kendoListView.dataSource;
var item = myDataSource.get(id);//need a check before attempting remove
myDataSource.remove(item);
}
common.LoadingGif("#mainView", true);
window.scrollTo(0, 0);
},
error: function (jqXHR, textStatus, errorThrown) {
var e = errorThrown;
}
});
});
}
我正在使用 MVC 和 Kendo (UI v2018.3.1017) ListView 来管理我称为 'MaximoList' 的列表。为了使列表对多个控制器可用,我利用了 MVC 提供的“TempData”对象。在创建(和销毁)时,我看到 MaximoList 对象正确反映了更改。但是为了反映 UI 中的变化,我必须刷新 (F5) (Chrome) 浏览器。
对控件的 CSHTML 引用相当简单:
<div class="col-md-3">
<div class="form-group">
<label style="white-space: nowrap;">Maximo Id's</label>
<a id="btnAddMaximoEntry" onclick=window.allIsos.addMaximoEntry() href="#" title='Add Maximo' style='margin-left: 8px'><i class='fa fa-upload'></i></a>
<div class="" id="divMaximoList">
</div>
</div>
</div>
控件的JS定义是:
function addMaximoListView(isoId, outageId) {
maximoListDataSource = new kendo.data.DataSource({
transport: {
read: { url: "/request/GetMaximoList", type: "GET", dataType: "json", cache: false },
create: { url: "/request/AddMaximoEntry", type: "Post", dataType: "json", cache: false },
destroy: { url: "/request/DeleteMaximoEntry", type: "POST", dataType: "json", cache: false },
update: {},
parameterMap: function (data, type) {
if (type == "read") { return { IsoId: isoId, OutageId: outageId }; }
if (type == "create") { return { MaximoId: data.MaximoId }; }
if (type == "destroy") { return { id: data.Id }; }
},
sortable: true,
pageable: true,
},
requestEnd: function (e) {
console.log(e.type);
console.log(e.response);
},
columns: [
{ field: "Id", Title: "Id", width: "0px" },
{ field: "MaximoId", Title: "MaximoId", width: "50px" },
{ command: ["edit", "destroy"], title: " ", width: "250px" }
],
autoSync: false,
schema: {
model: {
id: "Id",
fields: {
Id: { editable: false },
MaximoId: { editable: true, type: "string" },
}
},
},
});
var getTemplate = ""
+ "<div>"
+ " <a onclick=window.allIsos.deleteMaximo(#:Id#) href='\#'><i class='fa fa-trash'></i></a>"
+ '#:MaximoId#</div>';
var editTemplate = ""
+ "<div>"
+ " <input type='text' data-bind='value: MaximoId' name='MaximoId' required='required' />"
+ " <div>"
+ " <a class='k-button k-update-button' href='\#'><span class='k-icon k-i-check'></span></a>"
+ " <a class='k-button k-cancel-button' href='\#'><span class='k-icon k-i-cancel'></span></a>"
+ " </div>"
+ "</div>";
$("#divMaximoList").kendoListView({
template: kendo.template(getTemplate),
editTemplate: kendo.template(editTemplate),
dataSource: maximoListDataSource,
pageSize: 5,
dataBound: function (e) {
console.log("ListView is bound and ready to render.");
}
});
};
将项目添加到列表的 JS 定义是:
var addMaximoEntry = function () {
var listView = $("#divMaximoList").data("kendoListView");
listView.add();
};
正在重新启动调试本地应用程序,这里是公开来自 API/Database:
的测试数据的控件我点击了我的添加按钮,在接受条目之前,请注意我的新 MaximoId 的输入值 'NotWorking':
接受输入后,请注意控件添加了一个新条目,但它是原始项目之一的幽灵:
但是在刷新页面 (F5) 后,请注意当 GET 触发从服务器端 TempData 对象拉取时,实际的 'NotWorking' 项目已被服务器正确接收,并且更新的 TempData 对象被传递给UI(包括新条目):
Create/Add 的 API 方法如下 - 我返回到 UI,更新后的 MaximoList 对象的 JSON 表示并使用它更新对象,刷新到 TempData["MaximoList"]:
[HttpPost, Route("AddMaximoEntry")]
public ActionResult AddMaximoEntry(string MaximoId)
{
var ignoreCase = StringComparison.InvariantCultureIgnoreCase;
try
{
List<MaximoEntry> maximoList = TempData["MaximoList"] != null ? TempData["MaximoList"] as List<MaximoEntry> : new List<MaximoEntry>();
var maximoId = MaximoId;// unnecessary variable, but used for testing against multiple method confgurations
var maximoEntry = new MaximoEntry();
maximoEntry.MaximoId = maximoId;
if (maximoList.Where(s => s.MaximoId.Equals(maximoEntry.MaximoId, ignoreCase)).FirstOrDefault() == null)
maximoList.Add(maximoEntry);
TempData["MaximoList"] = maximoList as List<MaximoEntry>;
return Json(maximoList, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
return new JsonResult
{
Data = new
{
id = 0,
Success = false,
Msg = "Something went wrong while adding to the Maximo List. Please contact system support!"
}
};
}
}
而 API GET 如下:
[HttpGet, Route("GetMaximoList")]
public ActionResult GetMaximoList(int IsoId, int OutageId)
{
try
{
List<MaximoEntry> maximoList = ODataGetMaximoList(IsoId, OutageId);
return Json(maximoList, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
return new JsonResult
{
Data = new
{
id = 0,
Success = false,
Msg = "Something went wrong while getting Maximo List. Please contact system support!"
}
};
}
}
最初,ADD(CREATE) 的 API 方法传回了 Maximo 条目的整个列表(JSON 数组)。
解决方案是仅传回最初传递给 ADD(CREATE) 方法的 model 对象的更新版本,包括新分配的“id”值。新创建的条目将有一个负索引值,稍后我将在 MERGE 语句中的数据库级别使用它(即主键的负值不应该存在于数据库中table)来同步数据库。
如果还不清楚,我正在使用 TempData["MaximoList"] 对象来维护跨 API 控制器的 Kendo ListView 控件的状态。将控件状态保存到 DB(利用 TempData 对象)将发生在更通用的控制器方法中,该方法不管理 TempData 对象的状态(adds/deletes/etc。)。
我还重新设计了 DESTROY(删除)组件以仅在成功的 API 调用时从 (UI) 列表中删除已删除的项目,并通过删除一个清理了 JS不需要反映 TempData 对象状态的控件的不必要集数。
我的 API ADD 方法现在是:
[HttpPost, Route("AddMaximoEntry")]
public JsonResult AddMaximoEntry(MaximoEntry model)
{
var ignoreCase = StringComparison.InvariantCultureIgnoreCase;
try
{
List<MaximoEntry> maximoList = TempData["MaximoList"] != null ? TempData["MaximoList"] as List<MaximoEntry> : new List<MaximoEntry>();
var minId = maximoList.Where(w => w.id <= 0);
model.id = minId.Count() == 0 ? -1 : minId.Select(s => s.id).Min() - 1;
if (maximoList.Where(s => s.maximoId.Equals(model.maximoId, ignoreCase)).FirstOrDefault() == null)
maximoList.Add(model);
TempData["MaximoList"] = maximoList as List<MaximoEntry>;
return Json(model, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
return new JsonResult
{
Data = new
{
Success = false,
Msg = "Something went wrong while adding to the Maximo List. Please contact system support!"
}
};
}
}
我还更新了我的 DELETE 方法,作为 HTTPDELETE 方法,并返回一个状态指示器来提醒调用 JS 操作结果:
[HttpDelete, Route("DeleteMaximoEntry")]
public JsonResult DeleteMaximoEntry(int id)
{
try
{
List<MaximoEntry> maximoList = TempData["MaximoList"] != null ? TempData["MaximoList"] as List<MaximoEntry> : new List<MaximoEntry>();
var itemToRemove = maximoList.SingleOrDefault(r => r.id == id);
if (itemToRemove != null)
maximoList.Remove(itemToRemove);
TempData["MaximoList"] = maximoList as List<MaximoEntry>;
return Json(new { success = true, responseText = $"id {id} deleted from TempData object" });
}
catch (Exception ex)
{
var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
return new JsonResult
{
Data = new
{
Success = false,
Msg = $"Something went wrong while deleteing Maximo Entry (id {id}). Please contact system support!"
}
};
}
}
SELECT (READ) 和 CREATE(Add) 的 JS 控件定义是:
function addMaximoListView(isoId, outageId) {
maximoListDataSource = new kendo.data.DataSource({
transport: {
batch: false,//default is false
read: { dataType: "json", cache: false, type: "GET", url: "/request/GetMaximoList" },
create: { dataType: "json", cache: false, type: "POST", url: "/request/AddMaximoEntry" },
parameterMap: function (data, type) {
if (type == "read") { return { IsoId: isoId, OutageId: outageId }; }
if (type == "create") { return { model: data }; }
},
},
requestEnd: function (e) {
console.log(e.type);
console.log(e.response);
},
autoSync: false,
serverFiltering: true,
schema: {
model: {
id: "id",
fields: {
maximoId: { editable: true, type: "string" },
}
},
},
});
var getTemplate = ""
+ "<div>"
+ " <a onclick=window.allIsos.deleteMaximo(#:id#) href='\#'><i class='fa fa-trash'></i></a>"
+ " #:maximoId#"
+ "</div > ";
var editTemplate = ""
+ "<div>"
+ " <input type='text' data-bind='value: maximoId' name='MaximoId' required='required' />"
+ " <div>"
+ " <a class='k-button k-update-button' href='\#'><span class='k-icon k-i-check'></span></a>"
+ " <a class='k-button k-cancel-button' href='\#'><span class='k-icon k-i-cancel'></span></a>"
+ " </div>"
+ "</div>";
$("#divMaximoList").kendoListView({
template: kendo.template(getTemplate),
editTemplate: kendo.template(editTemplate),
dataSource: maximoListDataSource,
dataBound: function (e) {
console.log("ListView is bound and ready to render.");
}
});
};
对于DESTROY(DELETE),我添加了这些JS方法(希望将这些元素嵌入到控件定义中):
var deleteMaximo = function (id) {
executeDeleteMaximo(id, "Are you sure you want to delete this Maximo entry?");
}
function executeDeleteMaximo(id, confirmMsg) {
common.LoadingGif("#mainView", false);
common.ConfirmDialog(true, confirmMsg,
function (reason) {
if (reason == "NO") {
common.LoadingGif("#mainView", true);
return false;
}
$.ajax({
type: "DELETE",
data: { id: id },
url: "/request/DeleteMaximoEntry",
success: function (response) {
var data = response;
if (data.success) {
var myDataSource = $("#divMaximoList").data().kendoListView.dataSource;
var item = myDataSource.get(id);//need a check before attempting remove
myDataSource.remove(item);
}
common.LoadingGif("#mainView", true);
window.scrollTo(0, 0);
},
error: function (jqXHR, textStatus, errorThrown) {
var e = errorThrown;
}
});
});
}