Search code examples
microsoft-dynamicsdynamics-crm-2015dynamics-crm-2016

Form loads twice and cancels my load event logic


I'm trying to get the "Get Products" ribbon action logic in the main Invoice form to be executed automatically when the form is in update mode.

The invoice is created through a business flow, that starts with an Opportunity.

Here's the code form the load event of the invoice onLoad event:

onFormLoad = function () {

    //if we are in update mode...
    if (Xrm.Page.ui.getFormType() == 2) {

        //if no products are present in the list...
        if (loadInvoiceProducts().length == 0) {
            Mscrm.CommandBarActions.getProducts();
        }
    }
};

loadInvoiceProducts = function () {
    //just a jQuery ajax call to the oData service... this works.
    var products = oDataQuery("InvoiceDetailSet?$filter=InvoiceId/Id eq guid'" + Xrm.Page.data.entity.getId() + "'");
    return products.results;
};

This works fine if I manually create a new order (the form is then in form mode == 1, create) and when I fill in the required fields and save, the form reloads in update mode, then the "Get Products" popup appears.

The problem is when the invoice is created through the business flow. The invoice form opens in create mode (through the business flow, all the required fields are already filled) and when I hit Ctrl-S, the code above is triggered, the form is in update mode, but then another refresh happens and then the code above is not run.

I have to hit F5 for it to be triggered again.

Has anyone attempted anything like this before ?

Thanks.


Solution

  • Recent versions of CRM have asynchronous form loading and refreshing, which is likely what you're running into. When a new record is created and saved, onload is triggered again, as you've noted. When an existing record is updated and saved, onload is not triggered again. To learn more about what's going on, add an onsave handler that cancels the save, like this:

    // Put this function into your script
    function cancelSave(econtext) {
        var eventArgs = econtext.getEventArgs();
        console.log("saveMode", eventArgs.getSaveMode()); // could help you figure out why form is saving
        eventArgs.preventDefault();
    }
    
    // And then put this line into your onload method
    Xrm.Page.data.entity.addOnSave(cancelSave);
    

    If after adding the handler your issue goes away, then the problem is that your existing record is being saved which does not trigger onload again as I mentioned. You will need to investigate why the form is saving:

    • Do you have other code that could be triggering a save?
    • If the console output from cancelSave shows 70 ("AutoSave"), it is auto-save (which you can disable system-wide or on your form specifically [search the sdk for preventAutoSave])
    • If the console output from cancelSave shows 2 ("Save and Close"), then something on your form might be causing navigation to occur (when auto-save is enabled, navigating away from a form with unsaved data triggers a save with mode 2)

    If you determine that it is a save event that is interfering but can't figure out where the save is coming from for some reason, then you can also take the approach of figuring out which form fields are dirty. Save events do nothing if there are no dirty fields, so if you could figure out and resolve the dirtiness, that would work around the problem. One easy way to see which fields are dirty is to enable auditing on the entity and then view the audit log to see which fields were changed with the save.