I have a multi-step UI that requires the user select a group from a TreeList. That group selection must then be used to feed into a Grid that is populated by People that are in that selected Group.
How do I do this? I've been using the PanelBar up to this point to perform multi-step processes. However, I've never had to base the data selection in step 2 with the selection from step 1. Can I late bind the Grid so it will go get its data when the host Tab is selected?
5 Answers, 1 is accepted
Hello, Joel,
Straight to your question - yes you can bind the grid on a later stage. You can do that at a given time of the lifecycle, using the Client API of the component and by executing the read method on the DataSource instance of the Grid:
var grid = $("#grid").getKendoGrid()
grid.dataSource.read()
The above will trigger the request for data binding, and at this point, you can take into consideration the selection.
Hope this would help.
Regards,
Nencho
Progress Telerik
I believe I'm close on this... but no cigar. The TreeList:
@(Html.Kendo().TreeList<
NameValueParent
>()
.Name("treelist")
.Columns(columns =>
{
columns.Add().Command(c => { c.Custom().Text("Select")
.Name("selectButton").ClassName("selectButton")
.Click("goDetail"); })
.Width(Glossary.Portal.ButtonWidth);
columns.Add().Field(e => e.Name);
columns.Add().Field(e => e.Description);
columns.Add().Width(330).Command(c =>
{
c.CreateChild().Text("Add");
c.Edit();
c.Destroy();
})
.HtmlAttributes(new
{
style = "text-align: center;"
});
})
.Events(ev => ev.DataBound("onDataBound"))
.Editable()
.Selectable(s => s.Mode(TreeListSelectionMode.Single))
.DataSource(dataSource => dataSource
.Create(create => create.Action("Create", "Site"))
.Read(read => read.Action("IndexJson", "Site").Data("getData"))
.Update(update => update.Action("Update", "Site"))
.Destroy(delete => delete.Action("Destroy", "Site"))
.Model(m =>
{
m.Id(f => f.Id);
m.ParentId(f => f.ParentId);
m.Expanded(true);
m.Field(f => f.Name);
}).Events(events =>
{
events.Error("onError");
})
).Height(540))
The goDetail script that stores the value in an id field tells the Grid to read:
function goDetail(e) {
e.preventDefault();
//alert("goDetail: " + e.toString());
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
//alert("goDetail: " + dataItem.id);
$('#itemId').val(dataItem.id);
var grid = $("#grid").getKendoGrid();
grid.dataSource.read();
}
The above script successfully tells the Grid to read. My Grid:
@(Html.Kendo().Grid<
NameValuePair
>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.Id);
columns.Bound(p => p.Name);
columns.Bound(p => p.Value);
})
.Pageable()
.Sortable()
.Scrollable()
.HtmlAttributes(new { style = "height:550px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("GridJson", "Site")
.Data("getData"))))
When reading I need to get the selected value from the TreeList fed into the Controller's parameter list. My attempt that is not working. I tried to just return the raw value... this is an attempt to give the parameter.name:value.
function getData() {
var id = document.getElementById("itemId").value;
alert(id);
if (id != null) {
var str = "'id': '" + id + "'";
alert(str);
return str;
} else {
return 0;
}
}
And finally my controller method. The id parameter value is always 0:
public IActionResult GridJson(
[DataSourceRequest] DataSourceRequest request,
int id)
{
NameValuePairList lst = new NameValuePairList();
for (int i = 0; i < 5; i++)
{
lst.Add(new NameValuePair()
{
Id = $"{i}",
Name = nameof(id),
Value = $"{id}"
});
}
var dsResult = lst.ToDataSourceResult(request);
return Json(dsResult);
}
Thanks again for your help,
Joel
Hello, Joel,
The Data function should return the key-value pair so that the controller can be aware of the parameter name to receive. Check this forum thread, where this is described in details:
In other words, the getData function should look similar to the below implementation:
unction getData() {
var id = document.getElementById("itemId").value;
alert(id);
if (id != null) {
var str = "'id': '" + id + "'";
alert(str);
return {
id: str
}
} else {
return 0;
}
}
Also, the param in the controller should probably be in string type
Regards,
Nencho
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.
I finally got to work through this in detail. TreeList Click Event puts the Item.Id value into a model.Item.Id field using the #itemId id on the form's input field. I then capture the KendoGrid and tell it to read. On Grid.Read, the Item.Id value is pulled out of the model and fed to the controller's parameter by "return { id: id }" (param name: param value) syntax.
$("#treelist").on("click", function (e) {
//alert("click");
var tree = $("#treelist").data("kendoTreeList");
//alert(tree == null);
var item = tree.dataItem($(e.target).closest("tr"));
//alert(item == null);
//alert(item.id);
$('#itemId').val(item.id);
var grid = $("#grid").getKendoGrid();
grid.dataSource.read();
});
Controller (Note: param is defined as int)
public IActionResult GridJson(
[DataSourceRequest] DataSourceRequest request,
int id)
{
NameValuePairList lst = new NameValuePairList();
for (int i = 0; i < 5; i++)
{
lst.Add(new NameValuePair()
{
Id = $"{i}",
Name = nameof(id),
Value = $"{id}"
});
}
var dsResult = lst.ToDataSourceResult(request);
return Json(dsResult);
}
Script:
<
script
type
=
"text/javascript"
>
function getData() {
// alert("grid.getData");
var id = document.getElementById("itemId").value;
// alert(id);
if (id != null) {
return { id: id };
} else {
return 0;
}
}
</
script
>
Grid:
<
div
class
=
"col-sm-4"
>
<
form
>
<
div
asp-validation-summary
=
"ModelOnly"
class
=
"text-danger"
></
div
>
<
input
type
=
"hidden"
id
=
"groupId"
asp-for
=
"Item.Id"
/>
<
div
class
=
"form-group"
style
=
"margin-right: 5%"
>
<
label
asp-for
=
"Item.Id"
class
=
"control-label"
></
label
>
<
input
asp-for
=
"Item.Id"
class
=
"form-control"
id
=
"itemId"
readonly
=
"true"
/>
<
span
asp-validation-for
=
"Item.Id"
class
=
"text-danger"
></
span
>
</
div
>
</
form
>
@(Html.Kendo().Grid<
NameValuePair
>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.Id);
columns.Bound(p => p.Name);
columns.Bound(p => p.Value);
})
.Pageable()
.Sortable()
.Scrollable()
.HtmlAttributes(new { style = "height:550px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("GridJson", "Site")
.Data("getData"))))
</
div
>
Hello, Joel,
The solution seems great! Thank you for sharing it with the community as well.
Regards,
Nencho
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.