Friday, August 1, 2014

Containing CRM client side Beast

CRM client SDK evolved considerably since its early days as the product team slowly fill in the gaps between desired and available.
The most noticeable change IMO is the shift from simple to a more complex ("namespaced") programming interface.
In this Keep it short and simple (KISS) world this type of long programming style is a big "ouch" or an itch that needs to be contained.

Here are a few coding concepts and principles you should consider before you start fighting the beast:
1. "Flatten the tree" (AMAP) - Write object shortcuts to make your code shorter ,more readable and hopefully more manageable.

e.g.
var xrmPage = Xrm.Page;
var data = xrmPage.data;
var ui = xrmPage.ui;
var context = xrmPage.context;
var nav = ui && ui.navigation;
var formSelector = ui && ui.formSelector;
//see usage below ...

2. "Simple Entry point" - Create a simple object that contains all the important functions / methods you usually utilize in CRM SDK.
Instantiate that object in your SDK (see #3) so it’s available to your form automatically.

e.g.
// XrmForm contains all useful functions
function XrmForm() {
        var xfrm = this;
        // method - get view port hight
        xfrm.Height = function() {
                return ui && ui.getViewPortHeight();
            }
            //method - get view port width
        xfrm.Width = function() {
                return ui && ui.getViewPortWidth();
            }
            //method - refresh ribbon
        xfrm.RefreshRibbon = function() {
                ui && ui.refreshRibbon();
                return xfrm;
            }
            //property – holds the entity name
        xfrm.EntityName = data && data.entity.getEntityName();
    }

// at the bottom of the file
var xrmForm = new XrmForm();

// in your form you can write
xrmForm.RefreshRibbon();
//or
alert(xrmForm.EntityName);

There are many advantages to this approach, to name a few:
1. A centralized SDK web resource is easily upgradable. If the API changes again, like it did in 2011, you only need to adjust and repair this single file.
2. Enables you to continually build your library capabilities upon existing improvements.
As you can see in my examples adding a new method to your specialized objects is very easy.

3. "Clear separation" - Create a single web resource (e.g. companyname_SDK.js) that contains all the technical stuff your forms require in order to implement business logic.
Your forms logic should ideally be written against your own KISS API implementation of CRM SDK.

4. "Building blocks" - Use available libraries such as jquery , odata and fetch in order to build a more robust API.
here is an example of using jquery in your code
function XrmForm() {
        var xfrm = this;
        //hide form recordset bar
        xfrm.HideRecordSet = function() {
                $('#recordSetToolBar').hide();
                return xfrm;
            }
            //show from recrodset bar
        xfrm.ShowRecordSet = function() {
                $('#recordSetToolBar').show();
                return xfrm;
            }
            //hide left navigation 
        xfrm.HideNavigation = function() {
            $('#crmNavBar').parent()
               .css("left", "0.1px")
               .hide().prev()
               .css({
                   left: "0px",
                   right: "0px"
                });
            return xfrm;
        }
    }

//bottom of file
var xrmForm = new XrmForm();

//in your forms you can write
xrmForm.HideRecrodSet().HideNavigation();

Note: although you can hide the left navigation using customizations, using the above technique allows you to code against the form selector and navigate between role forms.

5. "Control the beast" – Wrap SDK objects and centralize their functionality under your own specialized objects. This way you can easily add functionality that is still missing in CRM.

e.g. adding missing Toggle method on a Boolean field
function XrmBooleanField(sId, iCtlIndex) {
    if (sId == undefined)
        return;

    var xbAttr = this;

    xbAttr.Toggle = function() {
        xbAttr.Set(!xbAttr.Get());
        return xbAttr;
    }

    xbAttr.Set = function(bValue, bDefault) {
        //setValue implementation …
    }

    xbAttr.Get = function() {
        //getValue implementation …
    }
}

//form usage 
var myBit = new XrmBooleanField("new_attr1");
myBit.Toggle();

6. "Look for patterns" – Utilize coding patterns such as chaining or cascading to make your code shine.

function XrmBooleanField(sId, iCtlIndex) {
    if (sId == undefined)
        return;

    var xbAttr = this;

    xbAttr.Toggle = function() {
        xbAttr.Set(!xbAttr.Get());
        return xbAttr;
    }

    xbAttr.Set = function(bValue, bDefault) {}
    xbAttr.Get = function() {}

    xbAttr.Require = function() {
        // implement setRequiredLevel …
        return xbAttr;
    }
}

//in your forms you can chain your methods like so …:
var myBit = new XrmBooleanField("new_attr2");
myBit.Require().Toggle();

This is just a small and hopefully tasty appetizer … more CRM frenzy in future posts …

No comments:

Post a Comment