Friday, January 27, 2012

Mapping Value from Parent Form to child View in CRM

Sometimes, you have to get the value from parent form and has to show in the child form. Clients may use 2 methods to open child view.
1. Using Associate Views
2. Using Sub Grid
3. Using button in ribbon

Base on the clients' selected method, we have to implement the code, because if the child form is created using Associate Views, window.parent.opener.Xrm.Page.data will be null and when calling from sub grids window.top.opener.parent.Xrm.Page.ui will be null.

So here, I have implemented a method to check both conditions. And in the Parent form, you may have a Lookup, int, decimal or picklist, that has to be mapped with different control in child page

Then, copy below function to your common Library JS (If you dont have a common JS web resource, it's time to create a one)

function MapFromParentForm(target, source)
{
    var targetControl = Xrm.Page.data.entity.attributes.get(target);
    var sourceControl;

    if (window.top.opener.parent != null && window.top.opener.parent.Xrm != null 
                    && window.top.opener.parent.Xrm.Page != null 
                    && window.top.opener.parent.Xrm.Page.ui != null)
    {        
        sourceControl = window.top.opener.parent.Xrm.Page.data.entity.attributes.get(source);
    }
    else if(window.parent != null && window.parent.opener != null 
                    && window.parent.opener.Xrm != null 
                    && window.parent.opener.Xrm.Page != null 
                    && window.parent.opener.Xrm.Page.data != null 
                    && window.parent.opener.Xrm.Page.data.entity != null 
                    && window.parent.opener.Xrm.Page.data.entity.attributes != null)
    {
        sourceControl = window.parent.opener.Xrm.Page.data.entity.attributes.get(source);
    }

    if (targetControl != null && sourceControl != null)
    {
        var sourceValue;
        if (sourceControl.getAttributeType() == "lookup")
        {
            sourceValue = sourceControl.getValue()[0].name;
        }
        else
        {
            sourceValue = sourceControl.getValue();
        }


        if (targetControl.getAttributeType() == "lookup")
        {
            targetControl.setValue(sourceValue)
        }
        else if (targetControl.getAttributeType() == "optionset")
        {
            targetControl.setValue(parseInt(sourceValue))
        }
        else
        {
            targetControl.setValue(sourceValue)
        }
    }
}


Then from the child Page form,
1. Add the Common Javascript web Resouce
2. And in form onLoad event, called the function as below

MapFromParentForm with the dynamic parameters as 'new_name', 'new_contactId' where 'new_name' is the control in child form and 'new_contactId' is in the parent form

3 comments:

  1. What to do if both window.top.opener.parent.Xrm.Page.data and window.parent.opener.Xrm.Page.data are null?
    Thats exactly what happens on Product Create form when opened from Look Up Record window.
    What to do if problem more difficult, the entities calling hierarchy is - Opportunity->New Opportunity Product ->New Product. Need to map Opportunitie's and Product fields. Grandfather Form. Could you advice something? Thank you.

    ReplyDelete
  2. Hello Vladimir,
    Unfortunately you cannot do this task as CRM opens Modal Dialog when you click the Lookup from the page. Unless CRM passes Page Data as an additional parameter to the Modal Dialog(Which CRM doesn't do), you cannot access parent data from Modal Dialog.
    You may need to implement a Workflow or a plugin in Product Entity so, once the user saves the Product, you can map the fields accordingly.

    ReplyDelete
  3. Hi again! Thank you for the answer. Now my task is the inverse mapping. Need to get the lookup value from child form and to show in the parent form lookup when child form saved. Child form opens with button in the ribbon. I obviously tried the same approach as in article, but what I see - I can't set parent form lookup value from child form. No error on setValue function, but parent form value just not updating. Yet cleaning with targetParentControl.setValue(null) is working.

    Could you advice how should be MapFromChildForm implemented?

    ReplyDelete