Monday, August 4, 2014

Working with Multiple Forms

Role forms are by far one of the most underestimated feature in CRM 2011/13.
Here are the reasons why I really like this cool feature:
1. Significantly reduces the load on your forms.
2. Allows you to better express business processes. Forms are minified and contain only fields that need to take part in a particular record state.
3. Allows control over who can see each form and thus facilitates the business workflow.
4. Allows for simple creation of wizard like applications.

With that said, I found that coding the form selector item needed a bit of work and as usual wrapped it in a way that enables me to navigate between forms with ease.

The first thing I did , as with other SDK objects, is wrap the form item in a specialized object called XrmFormItem. The XrmFormItem accepts both form id and name (or index) and does a double search to ensure that the form is found.

function XrmFormItem(oFormId) {
    if (!oFormId) return;

    var xfItem = this;
    var oForm = formSelector.items.get(oFormId) ||
        formSelector.items.get(function(item, index) {
            return item.getLabel() == oFormId;
        })[0];

    xfItem.Exists = function() {
        return !!oForm;
    };

    if (!xfItem.Exists()) return xfItem;
    xfItem.FormId = oForm.getId();
    //get form name
    xfItem.GetLabel = function() {
        return oForm.getLabel();
    }
    //navigate to a different form
    xfItem.Navigate = function() {
        if (formSelector.getCurrentItem().getLabel() != xfItem.GetLabel())
            oForm.navigate();
    }

    xfItem.toString = function() {
        return xfItem.GetLabel();
    }
}

Secondly, I created XrmForm methods to encapsulate all the logic involved in manipulating the forms.
Note: This is a partial implementation of XrmForm. For complete implementation click here.

function XrmForm() {
    var xfrm = this;
    // new additions for form selector and role forms
    xfrm.GetForms = function() {
            var aItems = [];
            var oArg = arguments[0];
            switch (typeof(oArg)) {
                case "string":
                case "number":
                    //get form by label or id or index
                    aItems[0] = new XrmFormItem(oArg);
                    break;
                case "function":
                    // get items that match a custom function
                    formSelector.items.get(function(item, index) {
                        var bResult = oArg(item, index);
                        if (bResult)
                            aItems.push(new XrmFormItem(item.getId()));
                        return bResult;
                    });
                    break;
                case "undefined":
                    //get all forms 
                    formSelector.items.get(function(item, index) {
                        aItems.push(new XrmFormItem(item.getId()));
                        return true;
                    });
                    break;
            }
            return aItems;
        }
    //get form by label or id or index
    xfrm.GetForm = function() {
            if (xfrm.HasMultipleForms())
                return xfrm.GetForms(arguments[0])[0];
            return null;
        }
    //debug forms
    xfrm.DisplayAvailableForms = function() {
            alert((function() {
                if (!xfrm.HasMultipleForms())
                    return "Only One form exists";
                var summary = "";
                forms = xfrm.GetForms();
                for (var f in forms) summary += forms[f].GetLabel() + "\n";
                return summary;
            })());
        }
    //navigate to another form
    xfrm.NavigateTo = function(frmLabel) {
        if (frmLabel && xfrm.HasMultipleForms()) {
            try {
                var xfItem = xfrm.GetForm(frmLabel);
                xfItem.Exists() && xfItem.Navigate();
            } catch (e) {}
        }
        return xfrm;
    }
   //true if more than 1 form exists for the current user 
    xfrm.HasMultipleForms = function() {
        return formSelector.getCurrentItem() != null;
    }
}

Now, all that remains is to navigate between role forms depending on specific scenarios e.g.

function OnCrmLoad() {
    //debug
    xrmForm.DisplayAvailableForms();

    var processTest = new XrmBooleanField("new_myformselectorbit");
    processTest.IsTrue() // getValue() === true;
        ? xrmForm.NavigateTo("First Role Form Name") 
        : xrmForm.NavigateTo("Secodnd Role Form Name");
}

Note: if the form becomes dirty CRM will present a dialog requesting save / discard changes so the
Best approach is to navigate between forms before it becomes dirty or by disabling all fields before navigation.

Fill free to add comments,
Cheers


No comments:

Post a Comment