0

I have the following code setup onLoad to generate a banner on a 'Shipment' record whenever the associated Account is marked as "Service Watch". The code currently functions, however it's generating an error alert "unable to get property '0' of undefined or null reference". This error occurs when the user is creating a new Shipment record, as the Account field doesn't have a value yet.

How can I configure the code to ignore a NULL value in the Account field?

function checkServiceWatch() {
    try{
        var account = Xrm.Page.getAttribute("cmm_account").getValue();
        var accountid = account[0].id;
        var formattedGuid = accountid.replace("}", "");
        accountid = formattedGuid.replace("{", "");
        // alert("Accountid: " + accountid);  // does that ID have brackets around it?
        // alert("Request: " + Xrm.Page.context.getClientUrl() + "/api/data/v8.2/accounts(" + accountid + ")?$select=cmm_servicewatch");

        var req = new XMLHttpRequest();
        req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.2/accounts(" + accountid + ")?$select=cmm_servicewatch", true);
        req.setRequestHeader("OData-MaxVersion", "4.0");
        req.setRequestHeader("OData-Version", "4.0");
        req.setRequestHeader("Accept", "application/json");
        req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        req.onreadystatechange = function()
        {
            if (this.readyState === 4) 
            {
                req.onreadystatechange = null;
                if (this.status === 200) 
                {
                    var result = JSON.parse(this.response);
                    var serviceWatch = result["cmm_servicewatch"];
                    // alert("serviceWatch: " + serviceWatch);
                    if(serviceWatch) //set notification
                    {
                        Xrm.Page.ui.setFormNotification("This Account is currently under Service Watch","WARNING","1");     
                    } // else 
                    // {
                    //   //Xrm.Page.ui.clearFormNotification("1");
                    // }  
                } 
                else 
                {
                    Xrm.Utility.alertDialog("Status: " + this.status + ", Text: " + this.statusText);
                }
            }
        };
        req.send();
    }
    catch (err) {
        alert("ServiceWatchCheckRibbon | checkServiceWatch " + err.message);
    }   
}

Should ignore records being created, but generate a banner on existing Shipments with Account values.

Pringle
  • 35
  • 8
  • Wrap the part you want to bypass in `if(account) {.......}`. Both `null` and `undefined` are [`falsy`](https://stackoverflow.com/questions/35642809/understanding-javascript-truthy-and-falsy). – PM 77-1 Sep 18 '19 at 14:16

4 Answers4

0

Assuming that account will hold an array and account id is not 0

You can either use length property to check if the account exist. If Yes then proceed else you can return

var account = Xrm.Page.getAttribute("cmm_account").getValue();

var accountid = account.length && account[0].id;

if(!accountid) return;

this Line will return the id into accountid if exist else returns 0

var accountid = account.length && account[0].id;

you can also add an additional check if you are not sure id exist in first element of account (account[0]) by adding

var accountid = account.length && (account[0] || {}).id;

which will return you undefined if you have elements in your account variable with the absence of key id

Only when account exist accountid variable will hold the account id if not it will have 0 or undefined which can be handled accordingly if you like to proceed or not.

Please let me know if I have solved your problem.

Community
  • 1
  • 1
  • Your code has the same problem as the one you are trying to fix. `undefined` does not have `length`. – PM 77-1 Sep 18 '19 at 14:57
  • please read the first line Assuming that account will hold at least an array. Or you can also add false check too to the below line var accountid = account && account.length && (account[0] || {}).id; – Senthur Athiban Sep 18 '19 at 15:05
  • whoever wanted to check for a falsy value of the account variable, It would fail when account holds an empty array. Unless you are sure about the account is not an array you can go with that check. But as per the question, I can see that you are using account[0].id so it might be an array of object. In that case, if you check for account != null account != undefined if(account) ... all the above will return true which will throw again unable to get property '0' of undefined or null reference you can use only use account!=false to check if it contains at least single object – Senthur Athiban Sep 19 '19 at 05:41
0

You have to check that the account variable has been initialised correctly. If it has, returning the variable will be equivalent to true and if it doesn't exist it will return false and not run the rest of the code in the try section. Correct code is below:

function checkServiceWatch() {
    try{
        var account = Xrm.Page.getAttribute("cmm_account").getValue();
        if(account) {
        var accountid = account[0].id;
        var formattedGuid = accountid.replace("}", "");
        accountid = formattedGuid.replace("{", "");
        // alert("Accountid: " + accountid);  // does that ID have brackets around it?
        // alert("Request: " + Xrm.Page.context.getClientUrl() + "/api/data/v8.2/accounts(" + accountid + ")?$select=cmm_servicewatch");

        var req = new XMLHttpRequest();
        req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.2/accounts(" + accountid + ")?$select=cmm_servicewatch", true);
        req.setRequestHeader("OData-MaxVersion", "4.0");
        req.setRequestHeader("OData-Version", "4.0");
        req.setRequestHeader("Accept", "application/json");
        req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        req.onreadystatechange = function()
        {
            if (this.readyState === 4) 
            {
                req.onreadystatechange = null;
                if (this.status === 200) 
                {
                    var result = JSON.parse(this.response);
                    var serviceWatch = result["cmm_servicewatch"];
                    // alert("serviceWatch: " + serviceWatch);
                    if(serviceWatch) //set notification
                    {
                        Xrm.Page.ui.setFormNotification("This Account is currently under Service Watch","WARNING","1");     
                    } // else 
                    // {
                    //   //Xrm.Page.ui.clearFormNotification("1");
                    // }  
                } 
                else 
                {
                    Xrm.Utility.alertDialog("Status: " + this.status + ", Text: " + this.statusText);
                }
            }
        };
        req.send();
    }
    }
    catch (err) {
        alert("ServiceWatchCheckRibbon | checkServiceWatch " + err.message);
    }   
}
LTPCGO
  • 448
  • 1
  • 4
  • 15
  • Well this works for all of our forms, excluding one. It's generating the same alert error on record creation. – Pringle Sep 23 '19 at 13:49
  • @Pringle without looking at the rest of the code it might be that `account` is a valid reference but not `account[0]`. Update `if(account) {` and `if(account && account[0]) {` – LTPCGO Sep 23 '19 at 21:51
  • Pay attention to `var account = Xrm.Page.getAttribute("cmm_account").getValue();` this will fail, if the field is not on the form. – Kiril Jan 08 '21 at 14:21
0

I will be doing like this always. Simply use this to do null check, stop execution & return.

    var account = Xrm.Page.getAttribute("cmm_account").getValue();
    var accountid; 

    if(account != null) 
        accountid = account[0].id.replace("}", "").replace("{", "");
    else
        return;
0

Please be aware that Xrm.Page is deprecated and will be replaced by the newer ExecutionContext. More information can be found at https://learn.microsoft.com/en-us/powerapps/developer/model-driven-apps/clientapi/reference/execution-context

I've modified the relevant part of your code to the new ExecutionContext, but you can still use the Xrm.Page library in case you don't want to switch (yet).

function checkServiceWatch(executionContext) {
    var formContext = executionContext.getFormContext();
    var account = formContext.getAttribute("cmm_account").getValue();
    if (!account) {
        return;
    }
    var accountid = account[0].id;
    // removed further code for brevity.
}

The if (!account) statement checks whether the account does not have an undefined or null value. The boolean statement works as null and undefined (along with NaN, 0 and empty strings) will resolve to false in a boolean context.

  • Thanks for the heads up Eric. We're not planning on moving the 9.0 anytime in the near future, but we're making a list of deprecated code and I'll add this alternative to it. Appreciate it! – Pringle Sep 23 '19 at 13:25