Quantcast
Channel: Hiding in Plain Sight » customizations
Viewing all articles
Browse latest Browse all 5

Creating a Multi-Entity Lookup in CRM 2011

$
0
0

In Microsoft Dynamics CRM 2011, there are certain lookups that will allow you to select from one of several different entity types. For example, on activities, there is the Regarding field, which allows you to choose from any entity that has activities enabled, as shown in the screenshot below.

Regarding Lookup

The regarding lookup is an example of the multi-entity lookup included in the CRM.

The ability to choose a single record from different entities is a very useful feature. The problem is, Microsoft did not include the ability for the CRM customizer or administrator to add lookups that reference multiple entities. When you create a lookup field, it can only reference the single entity is was created to map to.

The Requirement

While it is most likely not possible that you would need as an extensive a list as what is used in the Regarding lookup on activities, it is quite possible that we would need to reference multiple entities from a single lookup. Let’s say, for example, that you want to identify a referral source when creating a lead. This referral source could be an account, a contact, or even another lead. So, in our case, we would want a lookup that will allow us to choose from any of those three entities.

The Problems

First thought would be to create a lookup to one entity only. From that, we would add JavaScript to allow you to look at the other entities. While that is part of the solution, it isn’t complete. If you try to save the record with a different entity type, you will receive an error.

The next thought would be to create hidden text fields to store the entity logical name, the entity id, and the name. Using JavaScript you would populate the lookup and the fields on load, save, and change. Again, this is part of the solution, but it also has a flaw. When you populate a lookup on load, and the lookup entity type differs, the save button does not function at all. It acts as if there were no changes to the form. In my search for a solution, I found several blogs that did exactly this. Perhaps it worked on earlier versions of the CRM, or they never had to go back and change any values on the form. Whatever the situation, it was not an ideal solution.

The Solution

The solution to the issue requires creating multiple lookups, one to each entity that would need to be referenced in the multi-entity lookup. Using JavaScript, we will show or hide the appropriate lookup fields, populate and clear data from the lookup fields as appropriate, and create the multi-entity lookup.

Lead Lookup Fields

Three lookup fields, one to each entity, all with the same label.

The first step in creating our “Referred by” multi-entity lookup is to create three new lookup fields. For simplicity sake, I have named the fields “Referral Account,” “Referral Contact,” and “Referral Lead.” These three fields are then added to the desired position on the lead form. It is important to make sure they are grouped together as displayed.

Once the three fields have been added to the form, you will want to edit the properties of each of the fields to rename the labels. In this case, I have changed all three fields to “Referred By.” In addition, I have hidden each of the fields by default, as we will use JavaScript to show the appropriate field.

The next step will be to create the JavaScript file and enter the appropriate code. There is one global variable and five functions required for the multi-entity lookup to function, display and save properly. I will break apart each function to explain their purpose.

var changedControl = null;

The first line of our JavaScript file contains our global variable, which is set to null. This variable will hold the name of the lookup that was changed. As any one of the three fields can be displayed, we need to know which lookup fields to update when the value of the visible lookup is changed.

function BuildLookup(lookupId, lookupEntityName, lookupType, lookupName)
{
    var lookup = new Array();
    lookup[0] = new Object();
    lookup[0].displayClass = "ms-crm-Lookup-Item";
    lookup[0].keyValues = new Object();
    lookup[0].values = new Object();
    lookup[0].onclick = "openlui()";
    lookup[0].id = lookupId;
    lookup[0].entityType = lookupEntityName;
    lookup[0].typename = lookupEntityName;
    lookup[0].name = lookupName;
    lookup[0].type = lookupType;
    return lookup;
}

The BuildLookup function is next in our JavaScript. This helper function will create the necessary lookup object that will populate both the hidden lookup field and the visible multi-entity lookup field.

function BuildMultiLookup(control)
{
    var lookupIcons = "/_imgs/ico_16_1.gif:/_imgs/ico_16_2.gif:/_imgs/ico_16_4.gif";
    var lookupNames = "account:1,contact:2,lead:4";
    var lookupTypes = "1,2,4";

    document.getElementById(control).setAttribute("lookuptypes", lookupTypes);
    document.getElementById(control).setAttribute("lookuptypeIcons", lookupIcons);
    document.getElementById(control).setAttribute("lookuptypesnames", lookupNames);

    var accountLookup = Xrm.Page.getAttribute("new_referralaccount").getValue();
    var contactLookup = Xrm.Page.getAttribute("new_referralcontact").getValue();
    var leadLookup = Xrm.Page.getAttribute("new_referrallead").getValue();
    var newLookup = null;

    if (!IsNull(accountLookup))
    {
        newLookup = BuildLookup(accountLookup[0].id, "account", accountLookup[0].type, accountLookup[0].name);
    }
    else if (!IsNull(contactLookup))
    {
        newLookup = BuildLookup(contactLookup[0].id, "contact", contactLookup[0].type, contactLookup[0].name);
    }
    else if (!IsNull(leadLookup))
    {
        newLookup = BuildLookup(leadLookup[0].id, "lead", leadLookup[0].type, leadLookup[0].name);
    }

    if (!IsNull(newLookup))
    {
        Xrm.Page.getAttribute(control).setValue(newLookup);
    }
}

The BuildMultiLookup function is another helper function that is used to create our multi-entity lookup. The top half of the function allows the lookup to reference the account, contact, and lead entities. The bottom half of the function builds the lookup data and displays the data in the multi-entity lookup field.

The lookupIcons, lookupNames, and lookupTypes might appear a little confusing at first glance. The question becomes, how do you know what to put there? You will notice that each of the entities have a certain type, which is their type code. You can easily change or expand this list using the same format, as long as you know the type code for the entity in question. To get the type code, simply open up the entity in your browser, and look at the URL querystring. The number that is after the etc is the type code for that entity. This will work for both the out-of-the-box entities, as well as any custom entities you create.

The image files for custom entities require special handling. The default icon path for a custom entity is as follows: /_Common/icon.aspx?iconType=GridIcon&objectTypeCode=10007 If you have added your own custom icon to your custom entity, you can find the path to your icon file from your web resources.

function Referral_OnChange(context)
{
    changedControl = context.getEventSource().getName();
    var lookup = Xrm.Page.getAttribute(changedControl).getValue();
    if (lookup != null)
    {
        var lookupId = lookup[0].id;
        var lookupName = lookup[0].name;
        var lookupType = lookup[0].type;

        if (changedControl != "new_referralaccount")
        {
            Xrm.Page.getAttribute("new_referralaccount").setValue(null);
        }
        if (changedControl != "new_referralcontact")
        {
            Xrm.Page.getAttribute("new_referralcontact").setValue(null);
        }
        if (changedControl != "new_referrallead")
        {
            Xrm.Page.getAttribute("new_referrallead").setValue(null);
        }

        if (lookupType == "1") // account
        {
            Xrm.Page.getAttribute("new_referralaccount").setValue(BuildLookup(lookupId, "account", lookupType, lookupName));
        }
        else if (lookupType == "2") // contact
        {
            Xrm.Page.getAttribute("new_referralcontact").setValue(BuildLookup(lookupId, "contact", lookupType, lookupName));
        }
        else if (lookupType == "4") // lead
        {
            Xrm.Page.getAttribute("new_referrallead").setValue(BuildLookup(lookupId, "lead", lookupType, lookupName));
        }
    }
}

The OnChange event is what will be called when any of the three referral lookups are changed. The context must be passed into the function in order to get the name of the control that triggered the event. The next task the function does is to clear all the other lookup fields, aside from the one that had triggered the function. Finally, the function will populate the data from the multi-select lookup into the appropriate lookup field (Account to account, contact to contact, lead to lead).

function Referral_OnLoad()
{
    var contactLookup = Xrm.Page.getAttribute("new_referralcontact").getValue();
    var leadLookup = Xrm.Page.getAttribute("new_referrallead").getValue();

    if (contactLookup != null)
    {
        Xrm.Page.ui.controls.get("new_referralcontact").setVisible(true);
        BuildMultiLookup("new_referralcontact");
    }
    else if (leadLookup != null)
    {
        Xrm.Page.ui.controls.get("new_referrallead").setVisible(true);
        BuildMultiLookup("new_referrallead");
    }
    else
    {
        Xrm.Page.ui.controls.get("new_referralaccount").setVisible(true);
        BuildMultiLookup("new_referralaccount");
    }
}

The OnLoad event is triggered when the form is loaded. This function will determine which of the lookup fields has data in it, and will display only that one lookup. If none of the fields have data, then it will display the referralaccount field by default. It will then call the BuildMultiLookup function earlier, to change the lookup into a multi-edit lookup.

function Referral_OnSave()
{
    if (changedControl != null)
    {
        var accountLookup = Xrm.Page.getAttribute("new_referralaccount").getValue();
        var contactLookup = Xrm.Page.getAttribute("new_referralcontact").getValue();
        var leadLookup = Xrm.Page.getAttribute("new_referrallead").getValue();

        if (changedControl == "new_referralaccount" && (contactLookup != null || leadLookup != null))
        {
            Xrm.Page.getAttribute("new_referralaccount").setValue(null);
        }

        if (changedControl == "new_referralcontact" && (accountLookup != null || leadLookup != null))
        {
            Xrm.Page.getAttribute("new_referralcontact").setValue(null);
        }

        if (changedControl == "new_referrallead" && (accountLookup != null || contactLookup != null))
        {
            Xrm.Page.getAttribute("new_referrallead").setValue(null);
        }
    }
}

The OnSave function performs some cleanup to the lookup fields before saving can occur. Because the multi-entity lookup is based on a single entity, it is not able to save the value if the entity type is a different type. For that reason, if the type differs, the lookup field is cleared prior to saving.

Custom Multi-Entity Lookup

The completed multi-entity lookup dialog.

Once all the pieces of the JavaScript file have been added and saved, it is necessary to make the final modifications to the form. In the form properties, for the event OnLoad, you will want to create an event that calls Referral_OnLoad. You will also want to create and event that calls Referral_OnSave for the event OnSave. Finally, edit the properties of each of the three fields. If you haven’t renamed and hidden them, do so at this time. You will also want to create an event that calls Referral_OnChange. When you create the event, it is important that you check the box for “Pass execution context in the first parameter.” As mentioned previously, this is necessary for the JavaScript to know which control had triggered the OnChange event.

With those changes done, it is time to save and publish your changes. Your new multi-entity lookup is now ready for use.


Filed under: Microsoft Dynamics CRM, Programming Tagged: CRM, customizations, JavaScript, Microsoft, microsoft dynamics crm, Microsoft Dynamics CRM 2011, technology

Viewing all articles
Browse latest Browse all 5

Latest Images

Trending Articles





Latest Images