I have a RadContextMenu implemented within a Radgrid and the options for the context menu are different for each row. To facilitate this I am using the Client-Side programming for the RadContextMenu and the ClientDataKeyName from the RadGrid to power the conditions.
This is all working fine. My problem is that I need some of the RadMenuItems to be Bold or have a different background color, but I see no way to do this through the Client-Side programming.
Am I missing something obvious here?
So for example here is where I need to change the Font to bold or Background color of the item
Snippet:
// if the item should be displayed, then initialize
if
(isItemDisplayed == 1) {
var
childItem =
new
Telerik.Web.UI.RadMenuItem();
var
displayText =
''
;
// Here I need to set childItem to be Bold and a specific background color to stand out
// set menu text
childItem.set_text(displayText);
// set employeeid identifier
childItem.set_value(employeeId);
// if we have items in the 'actions menu', then add it to the parent'
if
(parentActionsItem.get_items().get_count() > 0) {
menu.get_items().insert(0, parentActionsItem);
}
Any help is greatly appreciated
5 Answers, 1 is accepted
You can access the DOM element for the menu item after you add it to the menu. Then, you can use JavaScript to set some CSS to the main element or any of its children elements:
// if we have items in the 'actions menu', then add it to the parent'
contextMenu.get_items().insert(0, childItem);
$telerik.$(childItem.get_element()).css(
"background-color"
,
"greenyellow"
);
$telerik.$(childItem.get_element()).find(
".rmLink"
).css(
"font-weight"
,
"bold"
);
For further customization and inspection of the elements, you can follow the suggestions in the first two points of the Improve Your Debugging Skills with Chrome DevTools blog post.
Another option is to set a CSS class to the item after you add it to the menu, and use your stylesheet to change the appearance:
contextMenu.get_items().insert(0, childItem);
childItem.set_cssClass(childItem.get_cssClass() +
" important-item"
);
//$telerik.$(childItem.get_element()).css("background-color", "greenyellow");
//$telerik.$(childItem.get_element()).find(".rmLink").css("font-weight","bold");
<style>
.important-item {
background-color
: greenyellow;
font-weight
:
bold
;
}
</style>
Regards,
Peter Milchev
Progress Telerik
Hi Peter -
Thanks this was helpful. However it seems any change I make only applies to the last item inserted into the menu hierarchy.
I've posted a more complete snippet of how it is currently being implemented. Can you direct me to how I would alter the style/css like you instructed but to affect just one specific item? The contents of the context menu will be potentially different on each row of the RadGrid it is being implemented on, which also could change the number of items in each instance of it. I could even locate this item by the menu item text/value associated with it if that helps, but I could not find a good object reference for this object that outlined much of what I am needing to know.
function
RowContextMenu(sender, eventArgs) {
var
menu = $find(
"<%=menuContext.ClientID %>"
);
var
evt = eventArgs.get_domEvent();
if
(evt.target.tagName ==
"INPUT"
|| evt.target.tagName ==
"A"
) {
return
;
}
var
index = eventArgs.get_itemIndexHierarchical();
document.getElementById(
"hidSelectedRowIndex"
).value = index;
var
selectedItem = sender.get_masterTableView().get_dataItems()[index];
var
employeeId = selectedItem.getDataKeyValue(
"EmployeeID"
);
var
statusHeaderId = selectedItem.getDataKeyValue(
"StatusHeaderID"
);
var
contextMenuOptions = selectedItem.getDataKeyValue(
"ContextMenuOptions"
);
sender.get_masterTableView().selectItem(sender.get_masterTableView().get_dataItems()[index].get_element(),
true
);
// track changes to menu
menu.trackChanges();
// clear existing menu items
menu.get_items().clear();
// initialize parent menu objects
var
parentNewItem =
new
Telerik.Web.UI.RadMenuItem();
parentNewItem.set_text(
'New'
);
var
parentViewItem =
new
Telerik.Web.UI.RadMenuItem();
parentViewItem.set_text(
'View'
);
var
parentActionsItem =
new
Telerik.Web.UI.RadMenuItem();
parentActionsItem.set_text(
'Actions'
);
// loop through items
for
(
var
i = 0; i < contextMenuOptions.length; i++) {
// based on the item index, take action
var
isItemDisplayed = contextMenuOptions.charAt(i);
// if the item should be displayed, then initialize
if
(isItemDisplayed == 1) {
var
childItem =
new
Telerik.Web.UI.RadMenuItem();
var
displayText =
''
;
// create menu item based on index
switch
(i + 1) {
case
1:
displayText =
"Menu Action 1"
;
break
;
case
2:
displayText =
"Menu Action 2"
;
break
;
case
3:
displayText =
"Menu Action 3"
;
break
;
}
// set menu text
childItem.set_text(displayText);
// set menu identifier
childItem.set_value(employeeId);
switch
(i + 1) {
case
1:
// add to menu 1
parentViewItem.get_items().add(childItem);
break
;
case
2:
// add to menu 2
parentNewItem.get_items().add(childItem);
break
;
case
3:
// add to menu 3
parentActionsItem.get_items().add(childItem);
break
;
default
:
// add to 'parent' menu
menu.get_items().add(childItem);
break
;
}
}
}
// if we have items in the 'actions menu', then add it to the parent'
if
(parentActionsItem.get_items().get_count() > 0) {
menu.get_items().insert(0, parentActionsItem);
}
// if we have items in the 'view menu', then add it to the parent
if
(parentViewItem.get_items().get_count() > 0) {
menu.get_items().insert(0, parentViewItem);
}
// if we have items in the 'new menu', then add it to the parent'
if
(parentNewItem.get_items().get_count() > 0) {
menu.get_items().insert(0, parentNewItem);
}
// commit changes to menu
menu.commitChanges();
// show menu
menu.show(evt);
evt.cancelBubble =
true
;
evt.returnValue =
false
;
if
(evt.stopPropagation) {
evt.stopPropagation();
evt.preventDefault();
}
}
I recommend adding the nodes to the nodes collection of the Menu before setting the text, value and any other properties.
function
RowContextMenu(sender, eventArgs) {
var
menu = $find(
"<%=menuContext.ClientID %>"
);
var
evt = eventArgs.get_domEvent();
if
(evt.target.tagName ==
"INPUT"
|| evt.target.tagName ==
"A"
) {
return
;
}
var
index = eventArgs.get_itemIndexHierarchical();
document.getElementById(
"hidSelectedRowIndex"
).value = index;
var
selectedItem = sender.get_masterTableView().get_dataItems()[index];
var
employeeId = selectedItem.getDataKeyValue(
"EmployeeID"
);
var
statusHeaderId = selectedItem.getDataKeyValue(
"StatusHeaderID"
);
var
contextMenuOptions = selectedItem.getDataKeyValue(
"ContextMenuOptions"
);
sender.get_masterTableView().selectItem(sender.get_masterTableView().get_dataItems()[index].get_element(),
true
);
// track changes to menu
menu.trackChanges();
// clear existing menu items
menu.get_items().clear();
// initialize parent menu objects
var
parentNewItem =
new
Telerik.Web.UI.RadMenuItem();
parentNewItem.set_text(
'New'
);
var
parentViewItem =
new
Telerik.Web.UI.RadMenuItem();
parentViewItem.set_text(
'View'
);
var
parentActionsItem =
new
Telerik.Web.UI.RadMenuItem();
parentActionsItem.set_text(
'Actions'
);
// Add the parent items before creating the child items
// if we have items in the 'actions menu', then add it to the parent'
if
(parentActionsItem.get_items().get_count() > 0) {
menu.get_items().insert(0, parentActionsItem);
}
// if we have items in the 'view menu', then add it to the parent
if
(parentViewItem.get_items().get_count() > 0) {
menu.get_items().insert(0, parentViewItem);
}
// if we have items in the 'new menu', then add it to the parent'
if
(parentNewItem.get_items().get_count() > 0) {
menu.get_items().insert(0, parentNewItem);
}
// loop through items
for
(
var
i = 0; i < contextMenuOptions.length; i++) {
// based on the item index, take action
var
isItemDisplayed = contextMenuOptions.charAt(i);
// if the item should be displayed, then initialize
if
(isItemDisplayed == 1) {
var
childItem =
new
Telerik.Web.UI.RadMenuItem();
var
displayText =
''
;
// create menu item based on index
switch
(i + 1) {
case
1:
displayText =
"Menu Action 1"
;
break
;
case
2:
displayText =
"Menu Action 2"
;
break
;
case
3:
displayText =
"Menu Action 3"
;
break
;
}
// Add the child items before setting their text and value
switch
(i + 1) {
case
1:
// add to menu 1
parentViewItem.get_items().add(childItem);
break
;
case
2:
// add to menu 2
parentNewItem.get_items().add(childItem);
break
;
case
3:
// add to menu 3
parentActionsItem.get_items().add(childItem);
break
;
default
:
// add to 'parent' menu
menu.get_items().add(childItem);
break
;
}
// set menu text
childItem.set_text(displayText);
// set menu identifier
childItem.set_value(employeeId);
}
}
// commit changes to menu
menu.commitChanges();
// show menu
menu.show(evt);
evt.cancelBubble =
true
;
evt.returnValue =
false
;
if
(evt.stopPropagation) {
evt.stopPropagation();
evt.preventDefault();
}
}
Then, before showing the menu, you can find the desired item, then get it's element using the API and style it with JavaScript:
<
div
style
=
"width: 100px; float: left; padding-top: 5px;"
>
<
telerik:RadImageButton
ID
=
"btaction"
runat
=
"server"
OnClientClicking
=
"showcontextmenu"
Image-Url
=
"https://via.placeholder.com/34x34"
Height
=
"34px"
Width
=
"34px"
></
telerik:RadImageButton
>
<
telerik:RadContextMenu
ID
=
"cmactions"
runat
=
"server"
EnableRoundedCorners
=
"True"
EnableShadows
=
"True"
EnableAriaSupport
=
"True"
OnItemDataBound
=
"cmactions_ItemDataBound"
RenderMode
=
"Auto"
>
<
Items
>
<
telerik:RadMenuItem
Text
=
"Item1"
></
telerik:RadMenuItem
>
<
telerik:RadMenuItem
Text
=
"Item2"
></
telerik:RadMenuItem
>
<
telerik:RadMenuItem
Text
=
"Item3"
></
telerik:RadMenuItem
>
<
telerik:RadMenuItem
Text
=
"Item4"
></
telerik:RadMenuItem
>
</
Items
>
</
telerik:RadContextMenu
>
</
div
>
<script>
function
showcontextmenu(sender, args) {
var
contextMenu = $find(
"<%=cmactions.ClientID %>"
);
var
childItem =
new
Telerik.Web.UI.RadMenuItem();
var
displayText =
''
;
// if we have items in the 'actions menu', then add it to the parent'
contextMenu.get_items().insert(0, childItem);
// set menu text
childItem.set_text(
"Custom"
);
// set employeeid identifier
childItem.set_value(
"2123"
);
// childItem is the client-side object of type RadMenuItem
// https://docs.telerik.com/devtools/aspnet-ajax/controls/menu/client-side-programming/overview#getting-the-instance-of-a-particular-radmenuitem
var
childItemElement = childItem.get_element()
$telerik.$(childItem.get_element()).css(
"background-color"
,
"greenyellow"
)
$telerik.$(childItem.get_element()).find(
".rmLink"
).css(
"font-weight"
,
"bold"
)
contextMenu.show(args.get_domEvent());
args.set_cancel(
true
);
}
</script>
Please modify the code and screenshot I have provided so that it is more clear what the issue is and what is the difference between the actual and desired appearance.
Regards,
Peter Milchev
Progress Telerik
Hi Peter -
I'm not sure this approach will work for me because of two things.
1) I have this implemented in a RadGrid so it needs to be dynamic to each row in the grid.
2) The items will change depending on the grid row selected, meaning the parent nodes will be potentially different as well. So Row 1 might have 3 master categories each with children, but Row 2 might have only one master category with some children.
I am struggling with this implementation here. Am I doing this wrong altogether? It feels like it is 90% there but I just can't get this simple styling to apply in the same dynamic manner that I am building the menus.
So when they click a row on the RadGrid that is when we initialize the menu based on a data item in that row, which indicates all of the options that should be enabled in this instance of the RadContextMenu
<
telerik:RadGrid
ID
=
"rgExample"
runat
=
"server"
>
<
ClientSettings
>
<
ClientEvents
OnRowContextMenu
=
"RowContextMenu"
/>
<
Selecting
AllowRowSelect
=
"true"
/>
</
ClientSettings
>
<!-- Other Grid Items Here -->
</
telerik:RadGrid
>
<
telerik:RadContextMenu
ID
=
"menuContext"
runat
=
"server"
OnItemClick
=
"menuContext_ItemClick"
/>
Then we have the client side script RowContextMenu which is called on the OnRowContextMenu event which I pasted earlier in the post. It then reads one of the values from the dataItem so it knows which context parents/children to build for this particular row.
All of this works perfectly. I just want to style each particular row slightly different to accentuate a default option for the user, but it will be different on each row.
From your example it looked like you have a static RadContextMenu which is not the case for me due to the dynamic nature of its implementation in the RadGrid.
Am I going about this approach wrong?
Thanks in advance
Your approach is valid and perfectly fine. Actually, the correct approach in this scenario is the second option provided by my colleague Peter in his first post. To resolve the "only last item gets styled" issue, you can first set the CSS class of the item before adding it to the collection of the menu. Otherwise, the childItem instance will always be the last item:
contextMenu.get_items().insert(0, childItem);
For instance, in the attached sample you can simply add this:
var
newItem =
new
Telerik.Web.UI.RadMenuItem();
newItem.set_text(
"Clicked: "
+ el.innerHTML);
newItem.set_cssClass(newItem.get_cssClass() +
" important-item"
);
sender.get_items().add(newItem);
CSS:
.important-item {
background-color
: greenyellow;
font-weight
:
bold
;
}
And you should be ready to go.
Regards,
Eyup
Progress Telerik