On one view I am calling another view and passing a variable on "click" via a dynamic ListView. The datasource is being populated onShow.
It is working as expected on first usage but if 1) go BACK and choose another option OR 2) complete the first entry and try to create a new one - it blows trying to read the e.dataItem.{somevar}. Ideas why?
app.myService = {
onShow: function (e) {
....
$("#lvLevel2Options").kendoMobileListView({
dataSource: kendo.data.DataSource.create({data: ds }),
template: $("#templateCategoryLevel2").html(),
click: app.myService.categoryClicked
});
}
categoryClicked: function (e) {
//It blows HERE but only on second pass
var id= e.dataItem.id;
....
}
Other info: I checked the source of the List and see the data-uid values are changing each time i view the page as I would expect since the datasource is being refreshed onShow (it needs to be because it is dynamic filtered data).
6 Answers, 1 is accepted
Most probably the problem comes from the fact that you are initializing the ListView every time the view is shown. Keep in mind that creating a widget on top of already created widget is unsupported and can cause some incorrect behavior. In your case when you first open the view the ListView is created from scratch and works as expected, and then when you navigate back you reinitialize the widget which causes an issue.
I would suggest you to use the init event of the view in order to initialize the widgets inside of it, as this will help you prevent such errors.
Regards,
Kiril Nikolov
Telerik
app.myService = {
onShow: function (e) {
....
$("#lvLevel2Options").kendoMobileListView({
dataSource: kendo.data.DataSource.create({data: ds }),
template: $("#templateCategoryLevel2").html(),
click: app.myService.categoryClicked
});
}
categoryClicked: function (e) {
//It blows HERE but only on second pass
var id= e.dataItem.id;
....
// >>> new code below
$("#lvLevel2Options").data("kendoMobileListView").destroy();
}
This seems like a hot reoccurring topic in the forums - now that I see my issue is the same of a lot of other peoples post.
After reading your response I added the method call to destroy the view as the user clicked away from it. It seemed to have fixed the problem.
- In this case is it safe or is the solution overlooking something?
- I have used this same technique (dynamically create views) to create dynamic listview inside of listviews. Is that safe? My views inside the views could end up with the same id names? If not got an example to point me to for the correct way of doing things.
Thanks
Craig
In this case I think I have fixed the problem by INIT the view and binding the datasource onShow:
onShow: function (e) {
.... //NOTE ds is a local array
var dsCatLevel2 = kendo.data.DataSource.create({data: ds });
$("#lvLevel2Options").data("kendoMobileListView").setDataSource(dsCatLevel2);
}, .....
The approach you have outlined in the last post is the recommended one. There is no need to destroy and re-create dynamic widgets just to rebind their data. You can go even further, by reusing the datasource component and setting its data dynamically, using the data method.
Regards,Petyo
Telerik
var detailsdataSource = new kendo.data.DataSource({
transport: {
read: "api/Details/?staffid=" + "<%=hdnuserid.Value%>" + "&indate=" + "<%=hdndateparam.Value%>"
, contentType: "application/json; charset=utf-8"
, type: "GET"
, data: $(this).serialize()
, dataType: "json"
}
, schema: {
model: {
fields: {
ClientName: { type: "string" }
, ProjectName: { type: "string" }
, Activity: { type: "string" }
, Hours: { type: "string" }
, WIPID: { type: "number" }
, EnabledString: { type: "string" }
, Approved: { type: "boolean" }
, LockDownDate: { type: "date" }
}
}
},
change: function (e) {
var data = this.data();
if (data.length == 0) {
window.location.href = "History.aspx";
}
}
});
function detailListViewDataBindInit() {
$("#detailsview").kendoMobileListView({
dataSource: detailsdataSource
, template: kendo.template($("#detailstemplate").html()),
click: function (e) {
//alert(e);
//alert(e.dataItem);
//alert(e.dataItem.WIPID);
var wipid = e.dataItem.WIPID;
var approved = e.dataItem.Approved;
var visString = e.dataItem.EnabledString;
if (visString.indexOf("hidden") == -1) {
if (approved == true) {
e.preventDefault();
}
else {
if (e.button !== undefined) {
switch (e.button.element.context.innerText) {
case "Edit":
break;
case "Approve":
ApproveTime(wipid);
break;
case "Delete":
if (confirm("Are you sure you want to delete this Time Entry?")) {
DeleteTime(wipid);
}
break;
}
}
}
}
else {
e.preventDefault();
}
}
});
}
function ApproveTime(wipid) {
//var request = $.ajax({
// type: "POST"
// , url: "api/ApproveTime/?wipid=" + wipid
// , dataType: "json"
//});
var request = $.ajax({
type: "GET"
, url: "api/ApproveTime/" + wipid
, dataType: "json"
});
request.done(function (msg) {
alert(msg);
RefreshData();
});
request.fail(function (msg) {
if (msg === null) {
msg = '';
};
alert("Request failed!" + "\n Please try it later.");
RefreshData();
});
}
function DeleteTime(wipid) {
//var request = $.ajax({
// type: "POST"
// , url: "api/ApproveTime/?wipid=" + wipid
// , dataType: "json"
//});
var request = $.ajax({
type: "GET"
, url: "api/DeleteTime/" + wipid
, dataType: "json"
});
request.done(function (msg) {
alert(msg);
RefreshData();
});
request.fail(function (msg) {
if (msg === null) {
msg = '';
};
alert("Request failed!" + "\n Please try it later.");
RefreshData();
});
};
function RefreshData() {
//$("#detailsview").data("kendoMobileListView").destroy();
detailsdataSource.read();
$("#detailsview").data("kendoMobileListView").refresh();
//detailListViewDataBindInit();
//detailsdataSource.read();
//$("#detailsview").data("kendoMobileListView").setDataSource(detailsdataSource);
// This works on Android and is the preferred Method
//var detailsview = $("#detailsview").data("kendoMobileListView").dataSource.read();
//$("#detailsview").data("kendoMobileListView").refresh();
// **********************************************
//var detailsview = $("#detailsview").data("kendoMobileListView").setDataSource(detailsdataSource);
// $("#detailsview").data("kendoMobileListView").dataSource.refresh();
//This actually works????
// window.location.href = "Details2.aspx?indate=" + "<%=hdndateparam.Value%>"
};
</
script
>
Your approach seems correct. In fact, calling dataSource.read should be enough - the datasource will automatically refresh any bound widgets when new data arrives. Is it possible for you to isolate the case in a runnable sample and send it to us? We will take a look.
Regards,
Petyo
Telerik