Friday, June 27, 2008

Are you sure you want to navigate away from this page?

Within a form's onload script, it's sometimes necessary to override the default value of a field. On a recent project, I ran into a scenario where this became necessary for the previous development team. They implemented a custom encryption solution where client-side code called a web service to decrypt CRM data. The script then set the DataValue (field text value) of various fields to the decrypted value.

The side-effect of that code was that every time a user opened a record and then closed it (not making any changes), they were prompted with an alert box with the question "Are you sure you want to navigate away from this page? Your changes have not been saved.". Needing to click OK after viewing records became very annoying for users so they asked me whether there was anything that could be done to avoid this unnecessary message.

In looking at the SDK and the built-in code that determines whether a form is "dirty", I discovered that it's possible to set the defaultValue of a control to the current DataValue of the control. In other words, after making changes to the properties of a control (those that use the defaultValue and DataValue properties), you can reset the default value for the control to the data value that was set by other code.

My first attempt at this was to place the following at the bottom of the form's onload script:

crmForm.all.new_regionid.defaultValue = crmForm.all.new_regionid.DataValue;

I thought for sure that would solve the problem, but it didn't. Due to the placement of the onload code in the rendered page, this code ran too early and thus did not have the desired effect.

The use of the JScript function "setTimeout" did the trick, as in this example:

window.setTimeout("crmForm.all.new_attorney.defaultValue = crmForm.all.new_attorney.DataValue", 2000)

I placed that line at the bottom of the form's onload script and the unwanted "are you sure" prompt stopped appearing.

The use of setTimeout means that the user must keep the form open for at least the number of seconds you specify for the code to work. Unless someone opened a form accidentally, two seconds should allow the code to work a vast majority of the time.

6 comments:

  1. I'm able to get this to work by doing the following:
    var o = crmForm.all.#fieldToUpdate#;
    var defaultValue = "something";

    //Set the attribute's DataValue to new default value (changes IsDirty to true)
    o.DataValue = defaultValue;
    //Set the attribute's defaultValue to the just set DataValue attribute (IsDirty is still true)
    o.defaultValue = o.DataValue;
    //Set the attribute's DataValue to the attribute's defaultValue to reset the 'IsDirty' flag (IsDirty is reset to false)
    o.DataValue = o.defaultValue;

    ReplyDelete
  2. Hi,
    I have a field that is updated by a workflow and onLoad, if this field value is greater than 3 then i set the checkbox value to true.
    So i am getting the same window even when no changes are made. How can i apply your method to fix the problem in my scenario?
    Thanks in advance

    ReplyDelete
  3. I don't understand why you want to wait 2 seconds before you code is run. If you put it at the end of your onload code, why would it even have to wait before you set the default value of the field? The code "crmForm.all.fieldschemaname.defaultValue = crmForm.all.fieldschemaname.DataValue;" should work by itself as long as you put it at the end of the code.

    ReplyDelete
  4. Ha, nevermind my first comment. I see that you expained why you put the settimeout. However, I tested it without the 2 timeout within a CRM setting and it worked fine.

    ReplyDelete
  5. How it will work with Lookup datatype.

    the below line return always false.
    alert(crmForm.regardingobjectid.DataValue ==crmForm.regardingobjectid.DataValue);

    ReplyDelete
  6. I only needed the 1st version, didn't need the 2nd timeout version. I guess the timeout thing is necessary if the fields are updated automatically in the background by other stuff after the onload event finished running.

    ReplyDelete