Thursday, April 9, 2009

Accessing and Controlling the CrmForm from an iframe.

If you write custom web applications in iframes that depend on the data in the parent form, it is important to run on up to date information to avoid user confusion.

Important! This requires that the Restrict cross-frame scripting box for your iframe is NOT checked.

image

Accessing attribute values on the Parent Form can be done simply by adding a parent.document in front of your normal attribute names. This gets you the values currently on the form, but doesn't guarantee those values have been saved.

var myAttributeValue = parent.document.crmForm.all.new_attribute.DataValue;

Parent Form Save "if modified" This is a nice method to call because if there are no modified values on the form it won't do anything and your application can continue on it's merry way.

parent.document.crmForm.Save();

Force a Parent Save Sometimes you want to force a save so that a Plug-in is called to do some additional calculations even though no attributes have been modified on your current form. The recalculate on the Opportunity, Quote, Order, and Invoice forms is a good example.

Note: The SubmitCrmForm method is not a MS supported method, but it hasn't changed in the last couple CRM revisions.

SubmitCRMForm( Mode, Validate, ForceSubmit, closeWindow)

Modes:
1 = Save, 2 = SaveAndClose, 7 = Send,
58 = SaveAsCompleted, 59 = SaveAndNew

Example: In this example I am forcing a save so that a plug-in is called on the Pre Update for the quote to create a new total value from the quote details that were filled in when the Quote was created from an Opportunity. These new fields were  mapped between the detail products see Mapping Note below. The iframe contains a button to do something that requires all of the data on the quote be up to date.

function RecalculateQuote() 
{ 
   if ( parent.document.crmForm.all.new_totalamount.DataValue == null)
   {    
    parent.document.crmForm.SubmitCrmForm(1, true, true, false);   
    return false;      
    } 
    
    parent.document.crmForm.Save();
}

The above JavaScript is made to work with an OnClientClick so that a return false will not generate a postback.

Why do we need a return false option?  If the validation fails, a message is generated for the user, the save is not performed, and you do not want your action to run.

The data has already been filled in, then the crmFrom.Save() will check to make sure that any modified fields on the form have been saved.

<asp:Button ID="RunMyNeatFeature" CssClass="button" runat="server" Text="Go" OnClick="RunMyNeatFeature_Click"
OnClientClick="javascript:return RecalculateQuote();"/>

For the button the OnClick will PostBack and run the functionality I care about only if the RecalculateQuote() is not false.

This safeguards the user from running the functionality with different data than what is on the screen when they press the "Go" button.

Mapping Note: For mapping details open SQL Management Studio and look at the EntityMapBase table to find the EntityMapId that has the SourceEntityName and TargetEntityName that you are interested in. Add your guid to the end of the URL below and it will bring up a form to map attributes between the Source and Target Entities.

http://yourcrmservername:5555//tools/systemcustomization/relationships/mappings/mappinglist.aspx?mappingId=