CRM 2013 Beta: JavaScript – Form/Control Notifications and Preventing Autosave

In this post I shall discuss some of the new ad exciting changes in the CRM 2013 SDK for client side JavaScript. In particular I shall highlight 4 new Xrm.page methods to do with placing notifications on a CRM 2013 form, and how to prevent auto-save via JavaScript.  To find out more, read on…

New JavaScript Methods in CRM 2013

Note: CRM 2013 is not due to be released until October 2013. The information provided in this blog might different from the final product.

As always, the best place to start on using JavaScript when coding for any Dynamics CRM version is the Microsoft MSDN site. In particular, “Use JavaScript with Microsoft Dynamics CRM” contains a wealth of information about best practices for writing client side scripts  for Dynamics CRM. Be aware that this site currently only shows information for Dynamics CRM 2011. I would assume it’ll contain information specifically for Dynamics CRM 2013 after it is officially released in October.

Form Notification and Control Notifications in CRM 2013

Often customers require the ability to display messages to the user dynamically based on certain data entries on a form as the user is working on the form. This requirement is achieved previously by  JavaScript “alert” messages based on conditional checks of values in the fields displayed on the form. For instance, in Dynamics CRM 2011, the “alert” message in JavaScript will produce a “pop-up” message box displaying certain information. The user must click “OK” on the message box before continuing.

JSFormNotification-01

In Dynamics CRM 2013 however, in order to minimise the number of pop-up windows, the new SDK now includes 2 types of new notification on the form which you can add/remove via JavaScript:

Form Notification

  • Xrm.Page.ui.setFormNotification(message, level, uniqueid)
    This Xrm method displays a notification on the top of the record.
    Message: message string to be displayed in the notification.
    Uniqueid: string identifier for this message
    Level arguments:

    • “ERROR” (notification uses system error icon)
    • “WARNING” (notification uses system warning icon)
    • “INFO” (notification uses system info icon)
  • Xrm.Page.ui.clearFormNotification(uniqueid)
    This Xrm method removes the form notification set by  “setFormNotification”.
    Uniqueid: string identifier of the form notification to be removed.

Control Notification

  • Xrm.Page.getControl(fieldName).setNotification(message)
    This Xrm method displays a message near the specified control on the form
    FieldName: name of the field on the form you wish to get the control of
    Message: message string to be displayed in the notification
  • Xrm.Page.getControl(fieldName).clearNotification()
    This Xrm method removes the control notification
    FieldName: name of the field on the form you wish to get the control of

Note: Xrm methods is not the only way to display notifications to users in CRM 2013. You can also use e.g. CRM 2013 business rules.

Example

Suppose you have the following requirements from a customer: on the account form, we would like to:

  1. Display an information banner on this account when the “Credit Limit” field is filled in but the “Payment Terms” is not.
  2. Display a warning banner on this account if its “Credit Hold” is “Yes”.
  3. Display a message near the “SIC Code” field of an account if this field contains a value but the data does not start with “SIC-“.

Again, you can fulfill the above requirements in different ways now in CRM 2013 without writing a single line of JavaScript, but for the purpose of this post, I shall meet the requirements using Form Notifications for 1) and 2), and Control Notification for 3).

Requirement 1) involves interactions between 2 fields “credit limit” and “payment terms”. We need to work out when the form notification should be set and when it should be removed. E.g. let’s create a method called “CreditLimitFormNotification” that does the following:

  • Set form notification when “credit limit” is not null and “payment terms” is null
  • Clear form notification when “credit limit” is not null and “payment terms” is not null (i.e. user has set the payment terms on the account), or when “credit limit” is null (i.e. user has not set the payment terms).

In code, this would be:

CreditLimitFormNotification: function () {

    //If credit limit field has data but payment term has no data,
    //set a form notification to notify user that payment term should be filled in.
    //If credit limit has no data then clear the form notification

    var creditLimitValue = Xrm.Page.getAttribute("creditlimit").getValue();
    var paymentTermsOptionSet = Xrm.Page.getAttribute("paymenttermscode").getValue();

    if (creditLimitValue != null && paymentTermsOptionSet == null) {
        Xrm.Page.ui.setFormNotification(
            "The credit limit contains a value. Please ensure payment terms for this account is completed.",
            "INFO",
            "creditLimitNotification");
    }
    else if ((creditLimitValue != null &&   paymentTermsOptionSet != null)
            || creditLimitValue == null) {
        Xrm.Page.ui.clearFormNotification(
           "creditLimitNotification");
    }
}

Requirement 2) is simpler to work with. Let’s create a method called “CreditOnHoldFormNotification” that does the following:

  • Set form notification when “credit hold” is set to “Yes”. Clear form notification when “credit hold” is set to “No”.
CreditOnHoldFormNotification: function () {

    //If account's credit is on hold, set a form notification
    //If account's creidt is not on hold, clear form notification

    var creditOnHoldOptionSet = Xrm.Page.getAttribute("creditonhold").getValue();

    if (creditOnHoldOptionSet == true) {
        Xrm.Page.ui.setFormNotification(
            "This account's credit is on hold. Do not process any orders for this account.",
            "WARNING",
            "creditOnHoldNotification");
     }
     else if (creditOnHoldOptionSet == false) {
        Xrm.Page.ui.clearFormNotification(
            "creditOnHoldNotification");
     }
}

Requirement 3) can be met by another method called “SICCodeControlNotification” that does the following:

  • Set control notification when “SIC Code” is filled in but data does not match the required “SIC-“. Clears control notification if “SIC Code” is null or if “SIC Code” contains data that meets the required “SIC-” format.
SICCodeControlNotification: function () {

    //If SIC Code is not null and data does not start with "SIC-", set control notification
    //If SIC Code is null or if SIC Code meets formating requirements, clear control notification

    var sicCodeValue = Xrm.Page.getAttribute("sic").getValue();

    if (this.SICInCorrectFormat(sicCodeValue) == false) {
        Xrm.Page.getControl("sic").setNotification("SIC Code format should begin with SIC-");
    }
    else {
        Xrm.Page.getControl("sic").clearNotification();
    }
}

Where the SIC Code Format check can be easily done by using regular expressions: e.g.

SICInCorrectFormat: function (value) {

    //Match value must start exactly with "SIC-"
    if (value != null) {
        var regexpPattern = /^SIC-/;

        if (value.match(regexpPattern) == null) {
            return false;
        }
    }
    return true;
}

Once the code is ready, I hook the following to the account form:

  • Account form “OnLoad” event: “CreditLimitFormNotification”, “CreditOnHoldFormNotification”.
  • Account form’s attribute “SIC Code” “OnChange” event: “SICCodeControlNotification”.

Now when I open an account form that has e.g. “Credit Limit” of £10000 but no “Payment Terms”, “Credit Hold” set to “Yes”, or “SIC Code” not in the correct format, I see the following form and control notifications.

JSFormNotification-02

Got-Cha’s on Form Notifications and Control Notifications

In the brave new world of CRM 2013, alas, very little is as simple as it first appears. The above 3 requirements have been met, but your customer might not be very happy with your work. Here is why:

  • Form and Control Notification by themselves are non-blocking event. It’s all very well to display “Credit On Hold” form notification or “SIC Code” format control notifications, however there is no JavaScript included in this discussion to block a user from saving the field values into database. E.g. a user can still go ahead and save a “SIC Code” that does not conform to the “SIC-” format requirement. Depending on whether this is included in your customer’s requirement, it can mean more JavaScript development to protect database values by e.g. block the account form’s manual save event and auto save events if “SIC Code” is not in the correct format. An “ERROR” form notification can be displayed to ensure the user is aware of this formatting issue.
  • Auto save in CRM 2013 causes the form to reload. CRM 2013 auto-saves a form every 30 seconds (you can turn it off but it’s not recommended by Microsoft). In the discussion above, I have only hooked the “SIC Code” control notification method to the “OnChange” event of “SIC Code”, and the “Credit Limit” and “Credit On Hold” methods to be “OnLoad” event of the account form. This means:
  1. A user might change e.g. “Payment Terms” or sets “Credit Hold” to “No” and expects the form notification to be immediately removed. This will not happen and notification is not removed until the form auto-saves (or user manually saves the form), and it triggers an auto-refresh of the form.
  2. A user sees a control notification near “SIC Code” but suddenly the form auto-saves which triggers the “OnLoad” of the form. As the SIC Code notification is only attached to the “OnChange” event of the field, the control notification disappears when form reloads.
  3. Similarly, a user might delete the “Payment Terms” field when “Credit Limit” contains data. User might expect an immediate form notification pop up to warn them to reset “Payment Terms” but this wouldn’t happen as the Form Notification methods are currently hooked on to the Account form “OnLoad” events.

While the code is correct, it is apparent that understanding which events to hook the methods to become very important. To address the above missing functionality, we need to trigger the following methods for the events:

  • Account form “OnLoad” event: “CreditLimitFormNotification”, “CreditOnHoldFormNotification”
  • Account form’s attribute “SIC Code” “OnChange” event: “SICCodeControlNotification”
  • Account form’s attribute “Credit Limit” “OnChange” event: “CreditLimitFormNotification”
  • Account form’s attribute “Credit Hold” “OnChange” event: “CreditOnHoldFormNotification”
  • Account form’s attribute “Payment Terms” “OnChange” event: “CreditLimitFormNotification”

Preventing Manual/Auto-Save with JavaScript in CRM 2013

Given the above example, how can we prevent manual/auto-save if “SIC Code” fails the formatting validation?

To address this, Xrm now has a new “Save Mode” of 70 which denotes a form’s auto-save event. This means we need a JavaScript function that passes in the form’s “econtext”, check for its “save mode”, prevent auto/manual-save if “SIC Code” validation fails. To do this, we need the following Xrm methods:

  • econtext.getEventArgs().getSaveMode()
    A return value of 1 denotes manual save or Xrm save
    A result value of 70 denotes auto-save
  • econtext.getEventArgs().preventDefault()
    This method prevents the “save” action.

Now all we have to do is put this logic into a JavaScript method that is triggered on the “OnSave” event of the Account form. Don’t forget to pass the form’s context as the first parameter when setting this up in CRM! Additionally, the method will show an “Error” form notification on the account warning users that they cannot save this form until the SIC Code formatting issue is resolved.


// Hook this method to the Account form "OnSave" event
// Pass execution context as first parameter when registering on form's OnSave event
OnFormSave_Account: function (econtext) {

    var eventArgs = econtext.getEventArgs();
    if (eventArgs.getSaveMode() == 70 //autosave
        || eventArgs.getSaveMode() == 1) //manual save or Xrm save
    {
        if (this.SetSICCodeFormNotification() == true) {
            //Prevent auto/manual save
            eventArgs.preventDefault();
        }
    }
}

Now when you type a value in “SIC Code” on the Account form and you either save manually or auto-save triggers in the background, this JavaScript method will fire to show an ERROR form notification and blocks this save action.

JSFormNotification-03

When the user corrects this formatting issue and manually save/autosave again, both the form and control notification for “SIC Code” will disappear and saving action will succeed.

JSFormNotification-04

Advertisements

8 thoughts on “CRM 2013 Beta: JavaScript – Form/Control Notifications and Preventing Autosave

  1. Hello, I like the article a lot.

    I tried your code, but it did not work until I replaced : with =, as for example in:
    SICCodeControlNotification: function() became SICCodeControlNotification = function().

    I’m sure I’m missing something here, could you please clarify?

    Thanks

    1. Hi Tanios,

      Thanks for your comment and interest in CRM 2013!

      You are absolutely right the code I posted in this article will NOT work if you simply do a “copy and paste”. Looking back at my original js, all the functions I posted in this article live inside a javascript library I was writing at the time. For brevity’s sake, I only posted the actual functions themselves to demonstrate how the Xrm methods can be used.

      Sorry for the confusion!

      For example, the structure of my script goes like this:

      PT.Account_Main = {

      OnFormLoad_Account: function(){
      //code here
      },

      OnFormSave_Account: function(){
      //code here
      },

      //more functions to follow

      }

      And when I want to refer to the function when hooking it to a form event, I need to refer to the function by its full name, like so:

      “PT.Account_Main.OnFormLoad_Account”

      Hope that make sense!

      Cheers,
      Priscilla.

  2. Hi, interesting and detailed article

    I was wondering how you actually set up these scripts is CRM2013, i’ve tried a few times but keep getting various error messages

    Thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s