I have a grid that has a detail template that contains a tabstrip which contains a further grid, along the lines of what is described in the previous forum post Grid with Tabstrip with Grid - Server Binding. This shows hierarchical data, with the child data being of the same type as the parent data.
I have a Kendo ContextMenu defined which I use to show a context menu with dynamically created and manipulated items on the rows in the parent grid. This works great. (The manipulation is enabling/disabling menu items based on flags hidden in the selected data rows). However I want to show the same context menu on the rows in the child grids, obviously the selected menu option should apply to the selected rows in the child grid.
How can I achieve this? Currently when I right click on a selected row in the child grid I still get the context menu for the parent grid. Is there a way to define a context menu but have the target set according to which grid selected rows the user right clicked on? I've got a simplified sample below that shows the approach I've used, I'm open to options or suggestions using either a Razor/server approach or using some javascript/jQuery magic.
001.
@using (Html.BeginForm("Index", "Home"))
002.
{
003.
Html.Kendo()
004.
.Grid(Model.Files)
005.
.Name("ParentDataGrid")
006.
.Columns(columns => {
007.
008.
columns.Bound(df => df.ExternalId)
009.
.HtmlAttributes(new { id = "externalId" })
010.
.Hidden(true)
011.
;
012.
013.
columns.Bound(df => df.OptionFlags)
014.
.HtmlAttributes(new { id = "flags" })
015.
.Hidden(true)
016.
;
017.
018.
columns.Bound(df => df.Reference)
019.
.Title("Reference")
020.
;
021.
022.
columns.Bound(df => df.SourcedDate)
023.
.Title("Submitted Date")
024.
.Format("{0:dd/MM/yy}")
025.
;
026.
027.
columns.Bound(df => df.FileName);
028.
})
029.
030.
.DetailTemplate(dt =>
031.
Html.Kendo()
032.
.TabStrip()
033.
.Name("Tabstrip." + dt.Id)
034.
.Items(items => {
035.
items.Add()
036.
.Text("Child files")
037.
.Content(
038.
@<
text
>
039.
@(Html.Kendo()
040.
.Grid<
DataFile
>()
041.
.Name(string.Format("childFileGrid_{0}", dt.ExternalId))
042.
043.
.Columns(columns => {
044.
columns.Bound(col => col.FileName)
045.
.Title("File name")
046.
;
047.
columns.Bound(col => col.SourcedDate)
048.
.Title("Created")
049.
.Format("{0:dd/MM/yy HH:mm:ss}")
050.
;
051.
})
052.
.DataSource(ds => ds.Ajax()
053.
.Read(read => read.Action("GetChildFiles", "Home")
054.
.Data(string.Format(@"{{parentFileId:""{0}""}}", dt.Id))
055.
)
056.
)
057.
)
058.
@(
059.
//this (attempted) context menu is not appearing at all
060.
Html.Kendo()
061.
.ContextMenu()
062.
.Name(string.Format("childFileGridContextMenu_{0}", dt.ExternalId))
063.
.Target(string.Format("#childFileGrid_{0}", dt.ExternalId))
064.
.Orientation(ContextMenuOrientation.Vertical)
065.
.Items(i => {
066.
i.Add().Text("Test entry");
067.
})
068.
.Events(ev => {
069.
ev.Open("childFileContextMenuOpened");
070.
})
071.
)
072.
</
text
>
073.
);
074.
075.
})
076.
.Render()
077.
)
078.
.DataSource(ds => ds
079.
.Server()
080.
.Model(model => model.Id(df => df.ExternalId))
081.
)
082.
.Render();
083.
084.
085.
086.
087.
}
088.
089.
090.
@(
091.
//this is the parent grid context menu, this is the only context menu that is appearing
092.
Html.Kendo()
093.
.ContextMenu()
094.
.Name("parentDataContextMenu")
095.
.Target("#ParentDataGrid")
096.
.Orientation(ContextMenuOrientation.Vertical)
097.
.Items(items => items.Add())
098.
.Events(ev => {
099.
ev.Open("parentFileContextMenuOpened");
100.
})
101.
)
102.
103.
<
script
>
104.
105.
function parentFileContextMenuOpened(e) {
106.
debugger;
107.
var parentGrid = $("#ParentDataGrid").data("kendoGrid");
108.
dataContextMenuOpened(e, parentGrid);
109.
}
110.
111.
function childFileContextMenuOpened(e) {
112.
//currently this doesn't get called...
113.
debugger;
114.
var childGrid = $("#????????").data("kendoGrid");
115.
dataContextMenuOpened(e, childGrid);
116.
}
117.
118.
function dataContextMenuOpened(e, targetGrid) {
119.
if ($(e.item).is("li"))
120.
return;
121.
122.
//debugger;
123.
124.
var selectedRows = targetGrid.select();
125.
126.
var rejectRows = getCanRejectRows(selectedRows);
127.
var approveRows = getCanApproveRows(selectedRows);
128.
var unrejectRows = getCanUnrejectRows(selectedRows);
129.
var canRejectRowsFlag = rejectRows.length > 0;
130.
var canApproveRowsFlag = approveRows.length > 0;
131.
var canUnrejectRowsFlag = unrejectRows.length > 0;
132.
133.
134.
debugger;
135.
var menuItems = [
136.
{
137.
text: "Status"
138.
,items: [
139.
{ text: "Reject", enabled: canRejectRowsFlag }
140.
, { text: "Approve", enabled: canApproveRowsFlag }
141.
, { text: "Unreject", enabled: canUnrejectRowsFlag }
142.
]
143.
}
144.
//, { cssClass: "k-separator", enabled: false }
145.
];
146.
147.
//this.setOptions({ dataSource: menuItems });
148.
e.sender.setOptions({ dataSource: menuItems });
149.
}
150.
151.
152.
function getRowsBySpecifiedFlag(selectedRows, flagValue) {
153.
return selectedRows .find("#flags")
154.
.filter( function (index) {
155.
//debugger;
156.
return (Number($(this).text()) & flagValue) == flagValue;
157.
} );
158.
}
159.
160.
function getCanRejectRows(selectedRows) {
161.
return getRowsBySpecifiedFlag(selectedRows, 1 <<
2
);
162.
}
163.
164.
function getCanApproveRows(selectedRows) {
165.
return getRowsBySpecifiedFlag(selectedRows, 1);
166.
}
167.
168.
function getCanUnrejectRows(selectedRows) {
169.
return getRowsBySpecifiedFlag(selectedRows, 1 << 3);
170.
}
171.
172.
</script>