Rules and Events

Exclusive offer: get 50% off this eBook here
Microsoft Dynamics CRM 2011 Scripting Cookbook

Microsoft Dynamics CRM 2011 Scripting Cookbook — Save 50%

Over 50 recipes to extend system customization in Dynamics CRM 2011 through client-side scripting with this book and ebook

$29.99    $15.00
by Nicolae Tarla | July 2013 | Cookbooks Enterprise Articles Microsoft

In this article by Nicolae Tarla,author of Microsoft Dynamics CRM 2011 Scripting Cookbook, we will cover the following topics:

  • Form load event usage
  • Form save event usage
  • Field change event usage
  • Working with tabs and sections
  • Combining events
  • Enforcing business rules

(For more resources related to this topic, see here.)

Handling specifc events is something everybody expects from an application. While JavaScript has its own event handling model, working with Dynamics CRM offers a different set of events that we can take advantage of.

The JavaScript event model, while it might work, is not supported, and defnitely not the approach you want to take when working within the context of Dynamics CRM.

Some of the most notable events and their counterparts in JavaScript are described in the following table:

Dynamics CRM 2011

JavaScript

Description

OnLoad

onload

This is a form event. Executes when a form is loaded. Most common use is to filter and hide elements on the form.

OnSave

onsubmit

This is a form event. It executes when a form is saved. Most common use is to stop an operation from executing, as a result of a failed validation procedure.

TabStateChange

n/a

This is a form event. It executes when the DisplayState of the tab changes.

OnChange

onchange

This is a field specific event. It executes when tabbing out of a field where you've changed the value. Please note that there is no equivalent for onfocus and onblur.

OnReadyStateComplete

n/a

This event indicates that the content of an IFrame has completed loading.

Additional details on Dynamics CRM 2011 specifc events can be found on MSDN at http://msdn.microsoft.com/en-us/library/gg334481.aspx.

Form load event usage

In this recipe, we will focus on executing a few operations triggered by the form load event. We can check the value of a specifc field on the form, and based on that we can decide to hide a tab, hide a field, and prepopulate a text field with a predefned value.

Getting ready...

Just as with any of the previous recipes, you will need access to an environment, and permissions to make customizations. You should be a system administrator, a system customizer, or a custom role configured to allow you to perform the following operations.

How to do it...

For the purpose of this exercise, we will add to the Contact entity a new tab called "Special Customer", with some additional custom fields. We will also add an option set that we will check to determine if we hide or not the fields, as well as two new fields: one text field and one lookup field. So let's get started!

  1. Open the contact's main form for editing.
  2. Add a new tab by going to Insert | Tab | One Column.
  3. Double-click on the newly added tab to open the Tab Properties window.
  4. Change the Label field of the tab to Special Customer.
  5. Make sure the show label is expanded by default and visible checkboxes are checked. Click on OK.
  6. Add a few additional text fields on this tab. We will be hiding the tab along with the content within the tab.
  7. Add a new field, named Is Special Customer (new_IsSpecialCustomer). Leave the default yes/no values.
  8. Add the newly created field to the general form for the contact.
  9. Add another new text field, named Customer Classifcation (new_ CustomerClassifcation). Leave the Format as Text, and the default Maximum Length to 100, as shown in the following screenshot:
  10. Add the newly created text field to the general form, under the previously added field.
  11. Add a new lookup field, called Partner (new_Partner). Make it a lookup for a contact, as shown in the following screenshot:
  12. Add this new field to the general form, under the other two fields.
  13. Save and Publish the Contact form.
  14. Your form should look similar to the following screenshot:
  15. Observe the fact that I have ordered the three fields one on top of the other. The reason for this is because the default tab order in CRM is vertical and across. This way, when all the fields are visible, I can tab right from one to another.

  16. In your solution where you made the previous changes, add a new web resource named FormLoader (new_FormLoader). Set the Type to JScript.
  17. Click on the Text Editor button and insert the following function:
  18. function IsSpecialCustomer()
    {
    var _isSpecialSelection = null;
    var _isSpecial = Xrm.Page.getAttribute("new_isspecialcustomer");
    if(_isSpecial != null)
    {
    _isSpecialSelection = _isSpecial.getValue();
    }
    if(_isSpecialSelection == false)
    {
    // hide the Special Customer tab
    Xrm.Page.ui.tabs.get("tab_5").setVisible(false);
    // hide the Customer Classification field
    Xrm.Page.ui.controls.get("new_customerclassification").
    setVisible(false);
    // hide the Partner field
    Xrm.Page.ui.controls.get("new_partner").setVisible(false);
    }
    }

  19. Save and Publish the web resource.
  20. Go back to the Contact form, and on the ribbon select Form Properties.
  21. On the Events tab, add the library created as web resource in the Forms Libraries section, and in the Event Handlers area, on the Form OnLoad add the function we created:
  22. Click on the Text Editor button and insert the following function:
  23. Click on OK, then click on Save andPublish the form
  24. Test your configuration by opening a new contact, setting the Is Special Customer field to No. Save and close the contact. Open it again, and the tab and fields should be hidden.

How it works...

The whole idea of this script is not much different from what we have demonstrated in some of the previous recipes. Based on a set form value, we hide a tab and some fields. Where we capture the difference is where we set the script to execute. Working with scripts executing when the form loads gives us a whole new way of handling various scenarios.

There's more...

In many scenarios, working with the form load events in conjunction with the other field events can potentially result in a very complex solution.

When debugging, always pay close attention to the type of event you associate your script function with.

See also

See the Combining events recipe towards the end of this article for a more complex recipe detailing how to work with multiple events to achieve the expected result.

Form save event usage

While working with the Form OnLoad event can help us format and arrange the user interface, working with the Form OnSave opens up a new door towards validation of user input and execution of business process amongst others.

Getting ready

Using the same solution we have worked on in the previous recipe, we will continue to demonstrate a few other aspects of working with the forms in Dynamics CRM 2011. In this recipe the focus is on the handling the Form OnSave event.

How to do it...

First off, in order to kick off this, we might want to verify a set of fields for a condition, or perform a calculation based on a formula. In order to simplify this process, we can just check a simple yes/no condition on a form.

How it works...

Using the previously customized solution, we will be taking advantage of the Contact entity and the fields that we have already customized on that form. If you are starting with this recipe fresh, take the following step before delving into this recipe:

  1. Add a new two-options field, named Is Special Customer (new_IsSpecialCustomer). Leave the default yes/no values.
  2. Using this field, if the answer is No, we will stop the save process.

  3. In your solution add a new web resource. I have named it new_ch4rcp2. Set its type to JScript.
  4. Enter the following function in your resource:
  5. function StopSave(context)
    {
    var _isSpecialSelection = null;
    var _isSpecial = Xrm.Page.getAttribute("new_isspecialcustomer");
    if(_isSpecial != null)
    {
    _isSpecialSelection = _isSpecial.getValue();
    }
    if(_isSpecialSelection == false)
    {
    alert("You cannot save your record while the Customer is not a
    friend!");
    context.getEventArgs().preventDefault();
    }
    }

  6. The function basically checks for the value in our Is Special Customer. If a value is retrieved, and that value is No, we can bring up an alert and stop the Save and Close event.
  7. Now, back on to the contact's main form, we attach this new function to the form's OnSave event.
  8. Save and Publish your solution.
  9. In order to test this functionality, we will create a new contact, populate all the required fields, and set the Is Special Customer field to No.
  10. Now try to click on Save and Close.
  11. You will get an alert as seen in the following screenshot, and the form will not close nor be saved.
  12. Changing the Is Special Customer selection to Yes and saving the form will now save and close the form.

There's more...

While this recipe only describes in a very simplistic manner the way to stop a form from saving and closing, the possibilities here are immense. Think about what you can do on form save, and what you can achieve if a condition should be met in order to allow the form to be saved.

Starting a process instead of saving the form

Another good use for blocking the save and close form is to take a different path. Let's say we want to kick off a workfow when we block the save form. We can call from the previous function a new function as follows:

function launchWorkflow(dialogID, typeName, recordId)
{
var serverUri = Mscrm.CrmUri.create('/cs/dialog/rundialog.aspx');
window.showModalDialog(serverUri + '?DialogId=' + dialogID +
'&EntityName=' + typeName +
'&ObjectId=' + recordId, null, 'width=615,height=480,resizable=1,statu
s=1,scrollbars=1');
// Reload form
window.location.reload(true);
}

We pass to this function the following three parameters:

  • GUID of the Workfow or Dialog
  • The type name of the entity
  • The ID of the record

See also

For more details on parameters see the following article on MSDN:

http://msdn.microsoft.com/en-us/library/gg309332.aspx

Field change event usage

In this recipe we will drill down to a lower level. We have handled form events, and now it is time to handle field events. The following recipe will show you how to bring all these together and achieve exactly the result you need.

Getting ready

For the purpose of this recipe, let's focus on reusing the previous solution. We will check the value of a field, and act upon it.

How to do it...

In order to walkthrough this recipe, follow these steps:>

  1. Create a new form field called new_changeevent, with a label of Change Event, and a Type of Two Options. Leave the default values of No and Yes. Leave the Default Value as No.
  2. Add this field to your main Contact form.
  3. Add the following script to a new JScript web resource:

    function ChangeEvent()
    {
    var _changeEventSelection = null;
    var _isChanged = Xrm.Page.getAttribute("new_changeevent");
    if(_isChanged != null)
    {
    _changeEventSelection = _isChanged.getValue();
    }
    if(_changeEventSelection == true)
    {
    alert("Change event is set to True");
    // perform other actions here
    }
    else
    {
    alert("Change event is set to False");
    }
    }

  4. This function, as seen in the previous recipes, checks the value of the Two Options field, and performs and action based on the user selection. The action in this example is simply bringing an alert message up.
  5. Add the new web resource to the form libraries.
  6. Associate this new function to the OnChange event of the field we have just created.
  7. Save and Publish your solution.
  8. Create a new contact, and try changing the Change Event value from No to Yes and back. Every time the selection is changed, a different message comes up in the alert.

How it works...

Handling events at the field level, specifcally the OnSave event, allows us to dynamically execute various other functions. We can easily take advantage of this functionality to modify the form displayed to a user dynamically, based on a selection. Based on a field value, we can defne areas or field on the form to be hidden and shown.

Microsoft Dynamics CRM 2011 Scripting Cookbook Over 50 recipes to extend system customization in Dynamics CRM 2011 through client-side scripting with this book and ebook
Published: March 2013
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

Working with tabs and sections

This recipe will show you how to work with tabs and sections on a form. You might have observed some bits of code in other recipes that allow you to hide a specifc tab if a condition is not met. Here, we will analyze how to hide and show these form elements.

Getting ready

For the purpose of this demonstration, we will be looking at the Contact form we have been working on until now. Reuse the same solution you have used already, or if you want to start a new one, create a new solution.

How to do it...

First off, let's focus on working with the tabs. These form elements have the advantage of generating a link on the navigation, allowing a user to browse directly to a specifc tab. They come in handy when you have a long entity form, and you don't want the user to scroll for too long.

On the top-left side of the Contact form, right underneath the ribbon, your will see the tab as shown in the following screenshot:

 

Observe the four tabs displayed by default on the contact.

Note that hiding a tab will not only hide the tab on the form, but will also remove the link in the tabs area.

We can show and hide tabs based on either a form event, such as the OnLoad or OnSave events, or based on a field event, such as the OnChange event. The code is the same, the only difference is what event we associate with our function.

For the purpose of this example, I want to hide a tab when the form loads, no matter what.

  1. Add a new web resource of type JScript, and insert the following function:

    function HideTab()
    {
    Xrm.Page.ui.tabs.get("notes and activities").setVisible(false);
    }

  2. Add the new web resource to the form libraries.
  3. Associate your function with the form OnLoad event.
  4. Save and Publish your solution.
  5. Test by creating a new contact. The Notes & Activities> tab will be hidden.
  6. Also, the form section is hidden from the user.

In order to revert this action, check for a form condition and run another function to display this tab again. You can define the condition to be either a value populated in a text field, or maybe a new "Notes Required" two-options field on the form. Check the value as described in the previous recipes, and call the following function to show the tab:

function ShowTab()
{
Xrm.Page.ui.tabs.get("notes and activities").setVisible(true);
}

Similarly with tabs, a form section is an area of the form situated within a tab. You can choose to leave the tab visible at all times, but hide or show only a section.

The following function hides a section on the Contact form on form load. For this case, I will be leaving the Notes & Activities tab visible, but I want to hide only the Activities section.

function HideSection()
{
Xrm.Page.ui.tabs.get("notes and activities").sections.
get("activities").setVisible(false);
}

Observe that, in order to get to a section, we have to retrieve the tab on which the section lives.

On the fip side, in order to show a section back on the form, the following function does the job:

function ShowSection()
{
Xrm.Page.ui.tabs.get("notes and activities").sections.
get("activities").setVisible(true);
}

Note that these functions assume that the tabs and/or section are already created on the form, and are only dealing with hiding and/or showing these form elements.

How it works...

The demonstration in this recipe revolves around the concept of defining what the user needs to see on an entity form, based on either a form event or a predefned rule. We do count on all these tabs and sections being generated ahead of time. All we are doing is showing and/or hiding them according to our business rules.

Getting to a tab in order to perform an action on it is achieved using the following line of code:

Xrm.Page.ui.tabs.get("tabName")

Once we have a reference to the tab, we can perform the required actions on it, such as show or hide the tab by setting the SetVisible property.

Additionally, getting to a section on the form is done through the tab it lives on. The following code gets a reference to the section:

Xrm.Page.ui.tabs.get("tabName").sections.get("sectionName")

From here on, we can perform other actions.

Combining events

In the previous recipes of this article we have seen some examples on working with the form UI based on either a predefined rule on form load, or on a field's onchange event. This example will focus on putting it all together in order to achieve a comprehensive result that actually can satisfy a realistic business rule.

Getting ready

Let's go back to the solution that we have worked with in the previous recipe. We will be using the same Contact form to implement this example. Following the Form load event usage recipe described earlier in this article, we can easily realize that it only works first time when the user loads a contact. How about if the user changes a value on the form? We have touched on the functionality a little bit in the following recipes, but let's put it all together now.

How to do it...

The following is what we want to achieve:

  • When a user opens a contact, if the contact is marked as special customer, we want to collect additional information about him/her.
  • When a user opens a contact that is not marked as special customer, we want to hide the additional fields.
  • When a user changes a contact from special to not special or back, we want the form to dynamically show or hide the fields.

Up until now, the first two conditions are met by the recipe described earlier. Now let's focus on the third requirements.

  1. Open your existing solution from the first recipe in this article.
  2. Open your JScript web resource in which you added the other functions.
  3. Add the following new function to this resource:
  4. function ChangeCustomer()
    {
    var _isSpecialSelection = null;
    var _isSpecial = Xrm.Page.getAttribute("new_isspecialcustomer");
    if(_isSpecial != null)
    {
    _isSpecialSelection = _isSpecial.getValue();
    }
    if(_isSpecialSelection == false)
    {
    // hide the Special Customer tab
    Xrm.Page.ui.tabs.get("tab_5").setVisible(false);
    // hide the Customer Classification field
    Xrm.Page.ui.controls.get("new_customerclassification").
    setVisible(false);
    // hide the Partner field
    Xrm.Page.ui.controls.get("new_partner").setVisible(false);
    }
    else if(_isSpecialSelection == true)
    {
    // show the Special Customer tab
    Xrm.Page.ui.tabs.get("tab_5").setVisible(true);
    // show the Customer Classification field
    Xrm.Page.ui.controls.get("new_customerclassification").
    setVisible(true);
    // show the Partner field
    Xrm.Page.ui.controls.get("new_partner").setVisible(true);
    }
    }

  5. Associate this function with the OnChange event of the Is Special Customer field, as shown in the following screenshot:
  6. Save and Publish your solution.
  7. Test your script by opening a contact, and changing the Is Special Customer value from Yes to No and back. You will observe the Special Customer tab being shown and hidden as you change the value, as well as the other two fields.

How it works...

Taking a closer look at the function presented earlier, there are really a handful of actions we take.

  1. First off, we begin by declaring our temporary variable that will store the value of the Is Special Customer field. This being a two-options field, we expect back a True/ False value. We set this to null, note that if it does not get assigned we can skip execution of any other code:
  2. var _isSpecialSelection = null;

  3. On the next line, we get a reference to the form field:
  4. var _isSpecial = Xrm.Page.getAttribute("new_isspecialcustomer");

  5. In the next section, we check to make sure that our form field reference indeed found a field on the form, and we get the value of that field into the frst variable we declared:
  6. if(_isSpecial != null)
    {
    _isSpecialSelection = _isSpecial.getValue();
    }

  7. Based on the value retrieved from the form field, we can start to act on other form elements. Observe that frst we check if the value is false, and then we hide the Form tab and fields:
  8. if(_isSpecialSelection == false)
    {
    // hide the Special Customer tab
    Xrm.Page.ui.tabs.get("tab_5").setVisible(false);
    // hide the Customer Classification field
    Xrm.Page.ui.controls.get("new_customerclassification").
    setVisible(false);
    // hide the Partner field
    Xrm.Page.ui.controls.get("new_partner").setVisible(false);
    }

  9. Then we check if the value is true so we can show these elements back to the user:
  10. else if(_isSpecialSelection == true)
    {
    // show the Special Customer tab
    Xrm.Page.ui.tabs.get("tab_5").setVisible(true);
    // show the Customer Classification field
    Xrm.Page.ui.controls.get("new_customerclassification").
    setVisible(true);
    // show the Partner field
    Xrm.Page.ui.controls.get("new_partner").setVisible(true);
    }

If the value is not assigned, and it remains null as we defned it at the beginning, we do not execute any code. If there is a requirement to execute an action for that case, you can easily add another else if block at the end.

There's more...

A few things we have to be aware of when designing our forms include the following aspects:

You cannot add new fields dynamically

Working with form elements in Dynamics CRM assumes that all these fields are precreated and added to the forms. You cannot dynamically create new form fields and add them.

Be mindful of form layout

While this might not catch your attention right away, depending on where you drop your field on the form, after a while you will observe that when you hide a field, the remaining fields underneath do not rearrange automatically. This is because, while you have your field hidden, it still exists on the page at that specifed location.

When designing your page, arrange your individual fields that you will hide in such a way so that when you hide one, it does not leave an obvious gap on the form. Either place them at the bottom of a section or tab, or place them in such an order that while you start showing them, they get added at the bottom of the previous one. This works in a case where you have a business progression expected, and you display items on the form as you progress through phases predefned.

See also

For additional references on using form programming, see the following MSDN article: http://msdn.microsoft.com/en-us/library/gg328261.aspx

Enforcing business rules

For this recipe, we will focus on a different entity. Let's have a look at Opportunity. The Opportunity is the result of a qualifed lead in many cases, but Dynamics CRM allows you to also add opportunities directly.

With opportunities, one of the fields we will focus on is the pipeline phase. For specifc scenarios, a pipeline phase is tracked, customized, and enforced. Business rules can defne the stages that defne each pipeline phase, and specifc rules that have to be met for an opportunity to progress to the next pipeline phase.

Getting ready

We can start by either reusing one of the previously created solutions or creating a new one. If you do not have a solution created, start by creating one.

How to do it...

We assume the following business rules

  • An Opportunity begins at 10 percent
  • An Opportunity progresses to 25 percent if the Rating field is set to Hot
  • An Opportunity progresses to 50 percent if a currency and price list are defned
  • An Opportunity progresses to 75 percent if a freight amount is defned

We will achieve this by using a combination of scripting and workfows. So let's get to it.

  1. Open your solution and add the Opportunity entity if not already added.
  2. Go to processes and add a new process. configure it as described in the following screenshot:
  3. Once you click on OK, the process information window opens up. Set the following items on this window:
    1. Set the Scope to Organization
    2. Set the Start when to Record is created
    3. Add an Update Record step
    4. In the Update make sure Opportunity is selected
    5. Click on Set Properties
  4. In the new form that opens find the Pipeline Phase field, and type in 10%, as shown in the following screenshot:
  5. Click on Save and Close.
  6. Your form now should look similar to the following screenshot:
  7. Click on Save and then Activate to activate your process.
  8. Click on Close.
  9. Now your processes window will show you the newly added process along with other processes previously added. Make sure that the Status shows Activated.
  10. Once we have this process, let's open a new Opportunity, fill in the required fields, and click on Save and Close. Give it a moment for the workfow to execute.
  11. Reopening the opportunity you just created should show you the customized 10% value added in the footer of the page, as seen in the following screenshot:
  12. Add a new workfow that updates the pipeline phase to 25 percent. configure it to kick off when the rating field changes value. We check if the rating value is Hot, and then we update the pipeline phase to 25 percent.
  13. Now we have to check if the Currency and Price List are defned. We will perform this check in JScript, and update a temporary field with a true/false value. Add a two-options field to the form, named new_progressto50.
  14. Insert the following script in a JScript resource, and associate it to the OnChange event of both the Currency (transactioncurrencyid) and Price List (pricelevelid) fields:
  15. code 17

  16. Create a new workfow similar to the previous one, that starts when the Progress to 50% field is changed, checks the field value, and if set to True, updates the pipeline phase to 50%.
  17. Finally, add a new workfow that starts when the Freight Amount field is changed, checks if the pipeline phase is at 50% and if the amount contains a value greater or equal to 0.00, and updates the pipeline phase to 75%.
  18. Save and Publish your solution.
  19. Test your solution by flling in progressively the required fields and follow how the pipeline phase updates automatically.

How it works...

The solution presented here enforces business rules through the use of workfows, and shows an example where working with JScript in conjunction with workfows can achieve the expected result.

For the sake of simplicity, I have demonstrated the creation of four different workfows, one for each phase progression. In real life, you would build all these rules in a single workfow. Additionally, you would probably build a reversed process that would downgrade the pipeline phase if a system value is changed to a value that does not allow the opportunity to pass a lower threshold.

Summary

In this article, we covered the following topics:

  • Form load event usage
  • Form save event usage
  • Field change event usage
  • Working with tabs and sections
  • Combining events
  • Enforcing business rules

Resources for Article:


Further resources on this subject:


Microsoft Dynamics CRM 2011 Scripting Cookbook Over 50 recipes to extend system customization in Dynamics CRM 2011 through client-side scripting with this book and ebook
Published: March 2013
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

About the Author :


Nicolae Tarla

Nicolae Tarla is a Senior Consultant in a Solutions Architect role. He has worked on various mid-size to enterprise-level Dynamics CRM and SharePoint solutions for both the private and public sectors. He has been delivering Microsoft Dynamics CRM solutions since the version 3.0 of the product. Nicolae also participated as a technical reviewer on the book Microsoft Dynamics CRM 2011: Dashboards Cookbook.

Books From Packt


Microsoft Dynamics CRM 2011 Reporting
Microsoft Dynamics CRM 2011 Reporting

Getting Started with Microsoft Dynamics CRM 2013 and xRM Application Development
Getting Started with Microsoft Dynamics CRM 2013 and xRM Application Development

Programming Microsoft Dynamics® NAV 2013
Programming Microsoft Dynamics® NAV 2013

Microsoft Dynamics AX 2009 Programming:Getting Started
Microsoft Dynamics AX 2009 Programming:Getting Started

Microsoft Dynamics AX 2009 Development Cookbook
Microsoft Dynamics AX 2009 Development Cookbook

Implementing Microsoft Dynamics NAV 2009
Implementing Microsoft Dynamics NAV 2009

Implementing SugarCRM
Implementing SugarCRM

 Microsoft Application Virtualization Advanced Guide
Microsoft Application Virtualization Advanced Guide


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software