- Toll Free: 1-866-SONOMA1
- Email Newsletter
- Blog
- YouTube
- Contact Us
Sonoma Partners
Adding Dynamic Menu Items
Posted by Jim Steger on December 21, 2009 |Today we welcome our guest blogger and colleague, Blake Scarlavai who discusses adding dynamic menu items to the CRM application.
The ISV config is helpful for when you need to add static menu items to the top of your entity form, but what about when you need dynamic menu items? In this blog post I will show you how to easily add dynamic menu items to the top of your entity form with the help of JavaScript and jQuery. I will be using the Opportunity entity and adding a menu of links to web pages at the top of the form.
First we need to add our base menu and a dummy menu item that will be used to help us create our dynamic menu items. We will do this in the ISV config like so:
<Entity name="opportunity"> <MenuBar> <CustomMenus> <Menu> <Titles> <Title LCID="1033" Text="Links" /> </Titles> <MenuItem JavaScript=""> <Titles> <Title LCID="1033" Text="Dummy Node" /> </Titles> </MenuItem> </Menu> </CustomMenus> </MenuBar> </Entity>
Here is what the menu looks like on our Opportunity form before we add any code:
Now that we have added our Links menu and dummy menu item, we can start writing the code.
My colleague Jeff Klosinski showed us how to dynamically load jQuery onto our CRM form in his blog post, http://blog.sonomapartners.com/2009/10/streamline-the-creation-of-new-related-records-with-jquery.html, which I reference below.
As we are going to be using jQuery, we will need to load it onto the form. In this example, I dynamically load jQuery from Microsoft CDN (Content Delivery Network). I’ll also declare Entity_OnLoad which is the function that will be called when the form is loaded. Here is what the code looks like:
var arr = new Array(), jQueryUrl = 'http://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.min.js', obj = document.createElement("<script src='" + jQueryUrl + "' type='text/javascript'>"); arr = document.getElementsByTagName("head"); arr[0].insertAdjacentElement("beforeEnd", obj); obj.attachEvent("onreadystatechange", Script_OnLoad);function Script_OnLoad()
{
var rs = event.srcElement.readyState;// check to see if the script is done loading
if (rs == "loaded" || rs == "complete")
{
Entity_OnLoad(); // jQuery is done loading and we can continue
}
}
function Entity_OnLoad()
{
// nothing yet
}
Note: Loading the jQuery library directly from Microsoft CDN may not be permitted in some environments and may not be available for offline/disconnected environments. Alternatively, you could copy the library locally to your CRM Web server or even paste the code from the library directly to the top of your form’s onLoad event.
Next we will create the function that returns our links:
function getLinks()
{
return [{ Name: "Bing", Url: "http://www.bing.com" }, { Name: "Sonoma Partners", Url: "http://www.sonomapartners.com" },
{ Name : "Facebook", Url : "http://www.facebook.com" }, { Name : "Twitter", Url : "http://www.twitter.com" }];
}
For the sake of this blog post I am just returning an array of an object that contains the name of the link that I want to display for the menu item and the actual url that I want to send the user to when they click the menu item. In production use, consider storing these links in a custom entity and use a web service to return the data.
Next we will create the function to return our dummy menu item that was created in the ISV config.
function getDummyMenuItem()
{
return $("li.ms-crm-MenuItem-Label[innerText='Dummy Node']");
}
In the code above, I am using jQuery to get the <li> element where the class is “ms-crm-MenuItem-Label” and the inner text is “Dummy Node”. This will find our “Dummy Node” menu item that was created in the ISV config and note that we are returning it as a jQuery object.
Next we will create our main function that we will call when the entity form loads:
function createLinksMenu()
{
// Get our dummy node so we can clone it
var dummyNode = getDummyMenuItem();
var links = getLinks();
if (!links || links.length == 0)
{
// Remove our dummy node if there is nothing to add
dummyNode.remove();
return;
}
// Loop through all the links
// then clone the dummy node, update it as necessary and append it to the menu
for (var i = 0; i < links.length; i++)
{
var clonedNode = dummyNode.clone(true);
clonedNode.find("span.ms-crm-MenuItem-Text")
.text(links[i].Name)
.end()
.attr("action", "window.open('" + links[i].Url + "');")
.attr("title", links[i].Name)
.appendTo(dummyNode.parent());
}
// Lastly remove our dummy node
dummyNode.remove();
}
In the code above, I am first getting the “Dummy Node” menu item as a jQuery object. We are returning this first as we may have to remove it if no links are returned. Next we are returning our links that we will use for our menu items. Then we check if any links are being returned, if there are then we can continue on, if not we will remove our “Dummy Node” menu item from the menu. If any links are returned then we loop through each one, clone the dummy node using jQuery, find the span with the class of ms-crm-MenuItem-Text (the actual display of the menu item), and we change it’s text to the name of our link. We then call end to revert the jQuery collection back to the cloned node and change the “action” attribute to open our link in a new window. Then we append our new cloned node to the dummy node’s parent. Lastly we remove our “Dummy Node” menu item from the menu.
Now we have all the functions written and we can update our Entity_OnLoad function to call our main function createLinksMenu:
function Entity_OnLoad()
{
createLinksMenu();
}
Once we import the ISV config and add this JavaScript to the entity form, then all we have to do is publish the entity and we are complete. Here is the finished product:
You could also easily extend this approach to conditionally display links based on record attributes (such as status) or the user’s security role.
Enjoy!
Comments
Contact Us for a Quote, or Personalized Demonstrationof Microsoft Dynamics CRM for Your Business.
Contact Us
Previous Post
Back to Blog
Post a Comment