I have a grid in master/detail like below.
CourseVM has an "Id" property as primary key (int)
As you can see, the detail grid uses a popup editor (custom editortemplate defined in /shared/EditorTemplates/CourseEntryVM.cshtml).
On that custom popup editor template, I need to have access to the master id (from CourseVM) in order to do some filtering for a dropdownlist, but I don't know how to have that Id.
Can anyone help me ?
Thanks
@(Html.Kendo().Grid<CourseVM>()
.Name(
"CourseGrid"
)
.DataSource(ds => ds
.Ajax()
.Events(events => events.Error(
"courseGridError"
))
.Model(model => model.Id(o => o.Id))
.Read(read => read.Action(
"Course_Read"
,
"Course"
))
.Destroy(destroy => destroy.Action(
"Course_Destroy"
,
"Course"
))
.ServerOperation(
false
)
)
.Columns(columns =>
{
columns.Bound(c => c.Id).Hidden();
columns.Bound(c => c.Number);
columns.Bound(c => c.OrganisationDisplay);
columns.Bound(c => c.BeginDate);
columns.Bound(c => c.EndDate);
columns.Command(commands =>
{
commands.Custom(
"Aanpassen"
).Click(
"courseEdit"
);
commands.Destroy().Text(
"Verwijderen"
);
}).Title(
"Commands"
).Width(200);
})
.ToolBar(toolbar =>
{
toolbar.Custom().Text(
"Nieuwe cursus inrichten"
).Action(
"Create"
,
"Course"
);
})
.Pageable()
.Sortable()
.ClientDetailTemplateId(
"courseDetailTemplate"
)
.Selectable(selectable => selectable.Mode(GridSelectionMode.Single))
)
<script id=
"courseDetailTemplate"
type=
"text/kendo-tmpl"
>
@(Html.Kendo().TabStrip()
.Name(
"tabStrip_#=Id#"
)
.SelectedIndex(0)
.Animation(animation => animation.Open(open => open.Fade(FadeDirection.In)))
.Items(items =>
{
items.Add().Text(
"Inschrijvingen"
).Content(
@<text>
@(Html.Kendo().Grid<CourseEntryVM>()
.Name(
"entryGrid_#=Id#"
)
.Columns(columns =>
{
columns.Bound(c => c.StudentDisplay);
columns.Bound(c => c.EntryDate);
})
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(c => c.StudentPersonAccountId);
})
.PageSize(30)
.Read(read => read.Action(
"Entry_Read"
,
"Course"
,
new
{ courseId =
"#=Id#"
}))
.Create(create => create.Action(
"Entry_Create"
,
"Course"
,
new
{ courseId =
"#=Id#"
}))
.ServerOperation(
false
)
)
.ToolBar(toolbar =>
{
toolbar.Create().Text(
"Inschrijving toevoegen"
);
})
.Editable(editable => editable.Mode(GridEditMode.PopUp))
.Pageable()
.Sortable()
.Events(events => events.Save(
"entryGridSaving"
))
.ToClientTemplate())
</text>
);
})
.ToClientTemplate()
)
</script>
16 Answers, 1 is accepted
Please check the example below how to achieve the desired behavior:
<script>
$(
function
() {
var
uid =
'#=uid#'
;
var
selector = kendo.format(
"tr[data-uid='{0}']"
, uid);
var
currentGridElement = $(selector).closest(
"[data-role=grid]"
);
var
parentRow = currentGridElement.closest(
".k-detail-row"
).prev();
var
parentGrid = parentRow.closest(
"[data-role=grid]"
).data(
"kendoGrid"
);
var
parentModel = parentGrid.dataItem(parentRow);
alert(parentModel.id);
} )
</script>
Regards,
Vladimir Iliev
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
thank you for your reply.
I'm a bit confused though. This seems to be an anonymous function. Do I need to place this in a specific event of the child grid ? If so, which one ?
Thanks
The previously provided code can be placed inside any function in the child Grid popup template in order to get the parent row model. For example you can place the same code inside "Data" function which returns additional parameters with each request (the parameter can be used for filtering the data):
@(Html.Kendo().DropDownListFor(m => m.Users)
.DataSource(d => d
.Read(read => read.Action(
"Read"
,
"User"
).Data(
"additionalData"
)
function
additionalData() {
var
uid =
'#=uid#'
;
var
selector = kendo.format(
"tr[data-uid='{0}']"
, uid);
var
currentGridElement = $(selector).closest(
"[data-role=grid]"
);
var
parentRow = currentGridElement.closest(
".k-detail-row"
).prev();
var
parentGrid = parentRow.closest(
"[data-role=grid]"
).data(
"kendoGrid"
);
var
parentModel = parentGrid.dataItem(parentRow);
return
{
parentModelId: parentModel.id
};
}
Regards,
Vladimir Iliev
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
Hugo,
I've tested the scenario with UI for ASP.NET Core and had no issues accessing the uid. A sample project is attached. The uid is logged in the console.
@{
ViewData["Title"] = "Home Page";
}
<h1>Grid:</h1>
@* @(Html.Kendo().Grid <TelerikAspNetCoreApp2.Models.ProductViewModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(o => o.Id).Width(110);
columns.Bound(o => o.ProductName).Width(110);
columns.Bound(o => o.Price);
columns.Bound(o => o.DateCreated).Format("{0:MM/dd/yyyy}").Width(200);
})
.Pageable()
.Sortable()
.Groupable()
.Scrollable()
.Filterable()
.HtmlAttributes(new { style = "height:550px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("Products", "Home"))
)
.ClientDetailTemplateId("template")
.Events(ev => ev.DataBound("onDataBound"))
)
*@
@(Html.Kendo().Grid<TelerikAspNetCoreApp2.Models.UserViewModel>()
.Name("userIdGrid")
.Columns(columns =>
{
columns.Bound(p => p.UserID);
columns.Bound(p => p.RoleID);
columns.Bound(p => p.ActiveFrom).Format("{0:MM/dd/yyyy}");
columns.Command(c =>
{
c.Edit();
});
})
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(p => p.RoleID);
model.Field("ActiveFrom", typeof(DateTime));
model.Field("ActiveTo", typeof(DateTime));
})
.Read(read => read.Action("UserRead", "Home"))
.Update(update => update.Action("UserUpdate", "Home"))
)
.Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("UserSiteInput"))
@* .ToClientTemplate() *@
)
<script id="template" type="text/kendo-tmpl">
</script>
<script>
function onDataBound() {
this.expandRow(this.tbody.find("tr.k-master-row").first());
}
</script>
Hugo,
In this scenario, you will have to use a different approach to get the uid value:
function additionalData(e) {
var ddlElement = $("#RoleID");
var uid = ddlElement.parents(".k-popup-edit-form").attr("data-uid");
console.log(uid)
}
Where RoleID is the name of the field the DropDownList is bound to:
@(Html.Kendo().DropDownListFor(m => m.RoleID)
...
thank you for your reply.
I cannot get it to work though.
This is the editor template of my child grid:
@(Html.Kendo().DropDownListFor(model => model.StudentPersonAccountId)
.DataTextField("FullName")
.DataValueField("Id")
.OptionLabel("(Kies student)")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetStudentsNotInCourseJson", "OptionList").Data("getCurrentCourse");
})
.ServerFiltering(false);
})
)
And this is the getCurrentCourse function as per your post:
function getCurrentCourse() {
var uid = '#=uid#';
alert(uid);
var selector = kendo.format("tr[data-uid='{0}']", uid);
var currentGridElement = $(selector).closest("[data-role=grid]");
var parentRow = currentGridElement.closest(".k-detail-row").prev();
var parentGrid = parentRow.closest("[data-role=grid]").data("kendoGrid");
var course = parentGrid.dataItem(parentRow);
return {
courseId: course.Id
};
}
You see that I "alert" the uid variable: the alert just says the text "#=uid" instead of an actual uid, so there must be something wrong.
Regards,
Mathieu
I was declaring the "getCurrentCourse" function on the main cshtml page, because I was under the impression that <script> sections in editortemplate.cshtml didn't work, so I always put it on the "main" page.
But now I found out that putting <script> section at the very top of the editortemplate.cshtml file does actually work, and then the uid variable gets resolved correctly.
Thanks for your help.
Basically your findings are correct - the script tags that contains functions which are referenced from the widgets inside the template should be placed at the top of the template. This is required as the widgets initialization code is wrapped in document "ready" event handler. The page however is already loaded and the scripts are immediately executed - before the referenced functions on the page are loaded.
Regards,
Vladimir Iliev
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
Hi.
I have a Master Grid, and the detail template have a TabStrip. Inside one for the tabs, I have a button in which, I have a javascript function on Click action.
My Master Grid:
01.
this
.Html.Kendo().Grid<Stock>()
02.
.Name(
"GridStock"
)
03.
/* code removed for briefness */
04.
.Columns(column =>
05.
{
06.
column.Bound(b => b.ProductId).Hidden(
true
);
07.
column.Bound(b => b.Description).Width(30);
08.
column.Bound(b => b.Supplier).Width(130);
09.
})
10.
.ClientDetailTemplateId(
"stockDetail"
)
My client template:
1.
<script id=
"stockDetail"
type=
"text/kendo-tmpl"
>
2.
@(
this
.Html.Kendo().TabStrip().Name(
"Tab_#=ProductId#"
).SelectedIndex(0)
3.
.Items(item =>
4.
{
5.
item.Add().Text(
"Tab1"
).LoadContentFrom(
"Tab1"
,
"MyController"
,
new
{ id =
"#= ProductId#"
});
6.
item.Add().Text(
"Tab2"
).LoadContentFrom(
"Tab2"
,
"MyController"
,
new
{ id =
"#= ProductId#"
});
7.
}).ToClientTemplate())
8.
</script>
And on Tab2.cshtml I have this:
1.
@(
this
.Html.Kendo().Button()
2.
.Content(
"New Request "
)
3.
.Name(
"buttonRequest_"
+
this
.Model.ProductId).HtmlAttributes(
new
{ type =
"button"
})
4.
.Events(events => events.Click(
"OpenRequestWindow"
)))
On this OpenRequestWindow I want to get data from GridStock.
How can I get data from my Master Grid?
Thanks,
Ezequiel
You can find the Grid object using the jQuery "closest" method as demonstrated below:
$(
"#somebutton"
).kendoButton({
click:
function
(e) {
var
grid =
this
.element.closest(
"[data-role=grid]"
).getKendoGrid();
}
});
Regards,
Vladimir Iliev
Telerik
Thanks Vladimir,
This is exactly what I need but what is the format in razor as I would like to extend the method from the view not javascript?
*** so instead of the following
$("#somebutton").kendoButton({
click: function(e) {
var grid = this.element.closest("[data-role=grid]").getKendoGrid();
}
});
*** the Razor version (as I see there is an option for defining the function directly instead of just providing the name
1.@(this.Html.Kendo().Button()
2. .Content("New Request ")
3. .Name("buttonRequest_"+this.Model.ProductId).HtmlAttributes(new { type = "button" })
4. .Events(events => events.Click(Func<obj,obj> handler)))
I want to wire it in the Razor View because I thought I could bind it to the row id without the javascript lookup from .closest("tr")
Can't I wire the row id directly in the .Click Func definition instead of just calling a click javascript handler name?
instead of looking it up in the handler call skipping this line below: var id = this.dataItem($(e.currentTarget).closest("tr"));
function loadModalDialogView(e) {
var id = this.dataItem($(e.currentTarget).closest("tr"));
var modalFormActionURL = "'/PCDB/GLDepartments/Edit/'";
var modalTitleLabel = "Editing Department";
var modalButtonText = "Update Department";
showModalAction(modalFormActionURL + $(sender).closest('tr').attr('data-uid'), modalFormActionURL, modalButtonText, modalTitleLabel);
}
Steven Packham
my apology I attached a mis-formated javascript function *Note(I do not want a bunch of loadDepartmentEditModalDialogView function to manage, but just want to define the function in the razor view)
--razor call: commands.Custom("Edit").Text("Edit").Click("loadDepartmentEditModalDialogView");
function loadDepartmentEditModalDialogView(e) {
var id = this.dataItem($(e.currentTarget).closest("tr")).id;
var modalFormActionURL = "/PCDB/GLDepartments/Edit/";
var modalTitleLabel = "Editing Department";
var modalButtonText = "Update Department";
showModalAction(modalFormActionURL + id, modalFormActionURL, modalButtonText, modalTitleLabel);
}
Binding it directly to the row is not possible out of the box when client rendering is used. In this case you should get the closest Grid using the example that I provide early. Please check the example below:
@(Html.Kendo().Button().Name(
"SomeButton"
).Events(e => e.Click(
"onClick"
)))
Regards,
Vladimir Iliev
Telerik
Lookup like you said of the events containing row, and its id works.
function loadAccountEditModalDialogView(e) {
var id = this.dataItem($(e.currentTarget).closest("tr")).id;
var modalFormActionURL = "/PCDB/GLAccounts/Edit/";
var modalTitleLabel = "Editing Account";
var modalButtonText = "Update Account";
showModalAction(modalFormActionURL + id, modalFormActionURL, modalButtonText, modalTitleLabel);
}
function loadAccountDeleteModalDialogView(e) {
var id = this.dataItem($(e.currentTarget).closest("tr")).id;
var modalFormActionURL = "/PCDB/GLAccounts/Delete/";
var modalTitleLabel = "Deleting Account";
var modalButtonText = "Delete Account";
showModalAction(modalFormActionURL + id, modalFormActionURL, modalButtonText, modalTitleLabel);
}
I think I originally used htmlattributes and set the onclick event and data wasn’t bound in then to my ‘tr’ or something, and this.dataItem always came up empty.
commands.Custom("Edit").Text("Edit").HtmlAttributes( onclick=”loadAccountEditModalDialogView()” )
But when you use the Kendo Grid’s columns.Command .Click action the e.currentTarget gets bound to the data on the click, and this.dataItem find the data.
.Columns(columns =>
{
columns.Bound(m => m.AccountDepartment).Title("Account").Width(175);
columns.Bound(m => m.Description).Title("Description").Width(175);
columns.Bound(m => m.AccountType).Title("Type").Width(125);
columns.Bound(m => m.Schedule).Title("Schedule").Width(110);
columns.Bound(m => m.TotalLevel).Title("Level").Width(75);
columns.Bound(m => m.Sequence).Title("Seq #").Width(75);
columns.Command(commands =>
{
commands.Custom("Edit").Text("Edit").Click("loadAccountEditModalDialogView");
commands.Custom("Delete").Text("Delete").Click("loadAccountDeleteModalDialogView");
});
})
Vladimir,
I am having issues running the code sample you provided. I too am trying to return some information from a parent grid to populate a dynamic dropdown list in a child grid.
To start off... if I hard-code a return value (for testing purposes) in my script, everything works fine as far as the EditorTemplate is concerned. Like this for example:
<script>
function getCurrentPublisher() {
return {
publisherID: 107
};
}
</script>
If I add the code in the examples above, somewhere I get an error, and I am having trouble debugging the issue. For instance, if I add the 1st few lines, and still hard-code my return value, the script does not error...
<script>
function getCurrentPublisher() {
var uid = '#=uid#';
window.alert(uid);
var selector = kendo.format("tr[data-uid='{0}']", uid);
var currentGridElement = $(selector).closest("[data-role=grid]");
var parentRow = currentGridElement.closest(".k-detail-row").prev();
var parentGrid = parentRow.closest("[data-role=grid]").data("kendoGrid");
return {
publisherID: 107
};
}
</script>
As soon as I add the line that references the parentGrid/ParentRow (after var parentGrid = parentRow.closest("[data-role=grid]").data("kendoGrid");) like this:
var authHead = parentGrid.dataItem(parentRow);
... well then I seem to just get stuck. The dropdown list shows a loading icon that spins indefinitely. If I try to access my 'authHead' object and return an actual, dynamic value, then my script goes into error and my dropdown list looks like a text box. So I am not sure that the'var authHead = parentGrid.dataItem(parentRow);' line of code is causing an error... it just never seems to move on.
Have you ever seen this before? Can ou think of a reason why this is not working? Also, is there a way I can show the UID of each row in the grid just for debugging purposes? I am using Kendo MVC 2017.3.1026.
Thanks,
-Bill
Vladimir,
You can ignore my prior post, thank you. I just realized I might be able to see the ID's in Chromes inspector. Turns out I was able to see the uid's and it helped me debug my issue! I think I am OK, now... everything is working as expected.
Thanks,
Bill
Hi
I have problem in Master and child grid dynamically Binding because i am using Uniqueidentifier datatype of ID
in clienttemplateID() have to show Invalid Template .
so please give me suggestion
@(Html.Kendo().Grid<ShipmentModel.Delivery.DoCreation_Viewmodel>()
.Name("gridmain1")
.Columns(columns =>
{
// columns.Bound(p => p.shipmentid_Guid).Width(100);
columns.Bound(p => p.mawbno).Width(120);
columns.Bound(p => p.hawbno).Width(120);
columns.Bound(p => p.ShipperName).Width(120);
columns.Bound(p => p.ConsigneeName).Width(120);
columns.Bound(p => p.NetWeight).Width(120);
columns.Bound(p => p.NetQty).Width(120);
columns.Bound(p => p.AvailableQty).Width(120);
columns.Bound(p => p.AvailableWeight).Width(120);
columns.Bound(p => p.Commodity).Width(150);
columns.Bound(p => p.branchname).Width(150);
})
.Pageable(p => p.PageSizes(new List<object> { 5, 10, 20, 100 }))
.Sortable()
.Scrollable()
.ClientDetailTemplateId("templatedelivery")
.Filterable(f => f.Mode(GridFilterMode.Row))
.HtmlAttributes(new { style = "height:400px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("DeliveryCreationlist", "Test"))
)
.Events(events => events.DataBound("dataBound"))
.Resizable(resize => resize.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
)
Child Gride is
<script type="text/x-kendo-template" id="templatedelivery">
@(Html.Kendo().Grid<ShipmentModel.Delivery.DoCreation_Viewmodel>()
.Name("grddel_#=shipmentid_Guid#")
.Columns(columns =>
{
columns.Bound(p => p.shipmentid_Guid).Width(100);
columns.Bound(p => p.mawbno).Width(120);
columns.Bound(p => p.hawbno).Width(120);
columns.Bound(p => p.ShipperName).Width(120);
columns.Bound(p => p.ConsigneeName).Width(120);
columns.Bound(p => p.NetWeight).Width(120);
columns.Bound(p => p.NetQty).Width(120);
columns.Bound(p => p.AvailableQty).Width(120);
columns.Bound(p => p.AvailableWeight).Width(120);
columns.Bound(p => p.Commodity).Width(150);
columns.Bound(p => p.branchname).Width(150);
})
// .Filterable(f => f.Mode(GridFilterMode.Row))
.HtmlAttributes(new { style = "height:400px;" })
.DataSource(dataSource => dataSource
.Ajax()
// .Model(model => model.Id(c => c.shipmentid_Guid))
.PageSize(20)
.Read(read => read.Action("ChildDelivery_Read", "Test", new { shipmentid_Guid = "#=shipmentid_Guid#" }))
)
.Pageable()
.Sortable()
.ToClientTemplate()
)
</script>
Thank you for the details.
I tried making an example using Uniqueidentifier datatype as ID, but the Grid was rendered as expected.
Could you please share with us the error message, and also the values of the shipmentid_Guid, as we can check if there are any, not allowed characters used as id.
I will be expecting the additional details and gladly assist further.
Regards,
Stefan
Progress Telerik