web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Microsoft Dynamics 365 | Integration, Dataverse...
Answered

Check the length of an Array of entities in JavaScript

(0) ShareShare
ReportReport
Posted on by 363

In my Javascript code I defined a variable of type Array, which will be populated with the entities retrieved from Dynamics Crm.

I need to check if the variable is populated both when it's a simple array and when it has become an array of entities: my code only works in the first case (for the simple array)

I defined the variable this way:

var arrayOfEntities = new Array();

This is the code to check whether the array is empty:


if (arrayOfEntities.length != 0) {
            return arrayOfEntities;
        }

The second time the previous instruction will be hit, arrayOfEntities will be already populated, so that I need to modify the condition: in fact, by asking if (arrayOfLength != 0), the condition is valued true even when there aren't entities in there.

I assume that the problem is that a simple array has a different structure than an array of entities: in the second case, "length" is a child node of "entities".

How can I modify my condition to make it valid in both cases?

I have the same question (0)
  • PabloCRP Profile Picture
    1,088 on at

    Hi, if you are using CRM Rest Builder the result contains the property "value" which is an array but if you are using Xrm.WebApi you will your result will have a "entities" property which is an array. so for validate if contains data could be:

    Crm Restbuilder : result.value.length !== 0;

    Xrm.WebApi:result.entities.length !==0;

    regards.

  • Joel D Profile Picture
    363 on at

    Hi,

    the object, when populated, has a property entities, and the property length is inside it, so that I changed my condition as in the following:

     
    
     if ((arrayOfEntities.length !== 0) || (arrayOfEntities.entities.length !== 0))

    ...but the instruction throws an error.


  • a33ik Profile Picture
    84,331 Most Valuable Professional on at

    Hello,

    Can you please provide your full code? It's hard to fix the part of something without seeing the full picure.

  • Joel D Profile Picture
    363 on at

    MyFunction_OnClick = function (executionContext) {
    
        var formContext = executionContext;
        var collectionid = formContext.data.entity.getId();
        var associatedStores = checkIfAssociatedStoress(collectionid);
    
        if (associatedStores.length != 0) {
            // perform tasks
        }
        else {
           // perform other tasks
        }
    }
    
    var associatedStores = new Array();
    
    
    checkIfAssociatedStoress = function (collectionid) {
    ava
        // need to set this condition properly:
        if (associatedStores.length != 0) {
            return associatedStores;
        }
    
        var storesFetchXml = // fetchXML to retrieve the stores whose collectionid_value is eq to collectionid
    
        storesFetchXml = "?fetchXml="   encodeURIComponent(storesFetchXml);
        Xrm.WebApi.retrieveMultipleRecords("new_store", storesFetchXml).then(
    
            function success(result) {
                associatedStores = result;
                // recall MyFunction_OnClick()
            },
            function (error) {
                Xrm.Navigation.openAlertDialog(error.message);
            }
        );
        return associatedStores;
    };

    Hi, this is the code.

    General overview: 

    associatedStores is a variable declared globally (line 15), it's being used to store the result of the WebApi call (line 31)-->
    As the WebApi call is asynchronous, when associatedStores is returned first time (line 38) is not populated, as it will be populated after the server response.
    So that my intention is to recall the MyFunction_OnClick() inside the callBack function: when the MyFunction_OnClick() is recalled, checkIfAssociatedStores() is called again (line 18), and this time the condition at line 21 is gonna be true, as associatedStores kept the value previously assigned inside the WebApi call. Therefore, its value is returned and I go back to line 7.

    My problem:

    the condition at line 7 (associatedStores.entities.length != 0) is valued true both when it contains entities and when has no entities inside, so that the check only works in the case when some entities are found from the WebApi call; if no entities are found, the associatedStores.length is > 0 is valued true as well, I assume it's because of the different structure of the result/object returned by the WebApi call (it has the additional child node "entities"). I tried to overcome the issue by writing the following to specify that the values I'm looking for are inside the child node "entities"  but the code does not work:

    if ((associatedStores.length !== 0) || (associatedStores.entities.length !== 0)) {
    return associatedStores;
    }

  • Suggested answer
    a33ik Profile Picture
    84,331 Most Valuable Professional on at

    Joel,

    As for me, you're trying to overcomplicate things.

    Here is the modified version of your code that uses Promise to work with async result of WebApi call:

    MyFunction_OnClick = function (executionContext) {
    	var formContext = executionContext;
    	var collectionid = formContext.data.entity.getId();
    	checkIfAssociatedStoress(collectionid).then(function(associatedStores) {
    		if (associatedStores.length != 0) {
    		// perform tasks
    		}
    		else {
    		// perform other tasks
    		}
    	},
    	function(error) {
    		Xrm.Navigation.openAlertDialog(error.message);	
    	});
    }
    
    checkIfAssociatedStoress = function (collectionid) {
    	return new Promise(function(resolve, reject) {
    		var storesFetchXml = // fetchXML to retrieve the stores whose collectionid_value is eq to collectionid
    
    		storesFetchXml = "?fetchXml="   encodeURIComponent(storesFetchXml);
    		Xrm.WebApi.retrieveMultipleRecords("new_store", storesFetchXml).then(
    			function success(result) {
    				resolve(result.entities);
    			},
    			reject);
    	});
    };
    

  • Joel D Profile Picture
    363 on at

    Hi,

    thank you very much for your sample with the Promise object.

    I modified my code, but it doesn't work for me, it's recognized by the browser but I can't debug it (I can't reach the debugger instruction at line 2) :

    _self.MyFunction_OnClick = function (executionContext) {
        debugger;
        var formContext = executionContext;
        var collectionid = formContext.data.entity.getId();
        checkIfAssociatedStores(collectionid).then(function (associatedLibraries) {
            if (associatedLibraries.length != 0) {
                console.log("ok");
            }
            else {
                 console.log("error");
            }
        },
            function (error) {
                Xrm.Navigation.openAlertDialog(error.message);
            });
    }
    
    checkIfAssociatedStores = function (collectionid) {
        return new Promise(function (resolve, reject) {
            var storesFetchXml = // fetch 
    
            storesFetchXml = "?fetchXml="   encodeURIComponent(storesFetchXml);
            Xrm.WebApi.retrieveMultipleRecords("new_store", storesFetchXml).then(
                function success(result) {
                    resolve(result.entities);
                },
                reject);
        });
    };

    I also tried by commenting out the return new Promise but it didn't work: 

    _self.MyFunction_OnClick = function (executionContext) {
        debugger;
        var formContext = executionContext;
        var collectionid = formContext.data.entity.getId();
        checkIfAssociatedStores(collectionid).then(function (associatedLibraries) {
            if (associatedLibraries.length != 0) {
                console.log("ok");
            }
            else {
                 console.log("error");
            }
        },
            function (error) {
                Xrm.Navigation.openAlertDialog(error.message);
            });
    }
    
    checkIfAssociatedStores = function (collectionid) {
        console.log("test");
    };

  • a33ik Profile Picture
    84,331 Most Valuable Professional on at

    What is _self at the start?

    Did you add the valid FetchXml to the line

    var storesFetchXml = // fetch

    ?

    Can you please provide the exact and full version of your code?

  • Joel D Profile Picture
    363 on at



    if (typeof (PREFIX) == "undefined") {
        PREFIX = { __namespace: true };
    }
    if (typeof (PREFIX.collection) == "undefined") {
        PREFIX.collection = { __namespace: true };
    }
    
    PREFIX.collection.Ribbon = new function () {
        var _self = this;
    
    
        _self.MyFunction_OnClick = function (executionContext) {
            debugger;
            var formContext = executionContext;
            var collectionid = formContext.data.entity.getId();
            checkIfAssociatedStores(collectionid).then(function (associatedLibraries) {
                if (associatedLibraries.length != 0) {
                    console.log("ok");
                }
                else {
                    console.log("error");
                }
            },
                function (error) {
                    Xrm.Navigation.openAlertDialog(error.message);
                });
        }
    
    
        checkIfAssociatedStores = function (collectionid) {
            return new Promise(function (resolve, reject) {
                var storesFetchXml = "";
    
                storesFetchXml = "?fetchXml="   encodeURIComponent(storesFetchXml);
                Xrm.WebApi.retrieveMultipleRecords("new_store", storesFetchXml).then(
                    function success(result) {
                        resolve(result.entities);
                    },
                    reject);
            });
        };
    
    }
    
    
    
    
    
    
    
      

    I'm using a namespace and the _self prefix refers to it.
    Yes, the fetchXml is valid, I already tested it, and it worked with my previous version of this code.

    On Ribbon Workbench, I added the function as Custom JavaScript Action to a command associated with a Ribbon button (complete name of the function including namespace: PREFIX.collection.Ribbon.MyFunction_OnClick )

  • Verified answer
    a33ik Profile Picture
    84,331 Most Valuable Professional on at

    Try to use the following code instead:

    if (typeof (PREFIX) == "undefined") {
        PREFIX = { __namespace: true };
    }
    if (typeof (PREFIX.collection) == "undefined") {
        PREFIX.collection = { __namespace: true };
    }
    
    PREFIX.collection.Ribbon = (function () {
    
        function myFunction_OnClick(executionContext) {
            debugger;
            var formContext = executionContext;
            var collectionid = formContext.data.entity.getId();
            checkIfAssociatedStores(collectionid).then(function (associatedLibraries) {
                if (associatedLibraries.length != 0) {
                    console.log("ok");
                }
                else {
                    console.log("error");
                }
            },
                function (error) {
                    Xrm.Navigation.openAlertDialog(error.message);
                });
        }
    
        function checkIfAssociatedStores(collectionid) {
            return new Promise(function (resolve, reject) {
                var storesFetchXml = "";
    
                storesFetchXml = "?fetchXml="   encodeURIComponent(storesFetchXml);
                Xrm.WebApi.retrieveMultipleRecords("new_store", storesFetchXml).then(
                    function success(result) {
                        resolve(result.entities);
                    },
                    reject);
            });
        };
    
        return {
    	MyFunction_OnClick: myFunction_OnClick
        };
    })();

    And to call the function use PREFIX.collection.Ribbon.MyFunction_OnClick function

  • Joel D Profile Picture
    363 on at

    Thank you very much,

    it works now.

    What if I wanted to add a spinner to tell the user to wait until the WebApi call returns the result?
    I tried by adding the following instructions before the api call (line 32 in your previous code) and inside the success and error callBack (line 34 and 36 in your previous code), but didn't work:

    Xrm.Utility.showProgressIndicator("Please wait...");  // at line 32, before the API call

    function success (result){ 
          Xrm.Utility.closeProgressIndicator();  // line 34
          resolve(result.entities);
    }, 
    Xrm.Utility.closeProgressIndicator();        //line 36
    reject);



    Secondly, as I'm new to JavaScript and Asynchronous calls, I'm trying to understand the architecture and syntax you made use of, can you please explain to me what's happening here?

    As far as I understood, the namespace PREFIX.collection.Ribbon is used like a function, and it contains two functions and a return instruction inside:
    1) myFunction_OnClick, which is being associated to the ribbon button; 
    2) checkIfAssociatedStores, which is being called by the former.
    3) And I have the return at line 40, I'm trying to understand this one. 

    You used:

    return {
    MyFunction_OnClick: myFunction_OnClick
    };


     and it works fine, whereas when I wrote return PREFIX.collection.Ribbon.MyFunction_OnClick didn't work (when I tried to use it, the function PREFIX.collection.Ribbon was reached even without clicking on the ribbon button, and the MyFunction_OnClick was never hit).
    So that I need to use the block of instructions that you provided at lines 40-42 to make things work: what the colon at line 41 stands for?
    Using the two curly braces after the return statement means that it's returning a function as value?

    As regards to the architecture (using the namespace as a function, putting everything inside it and returning the main function that way), is it used when we have to handle with asynchronous calls? And does this pattern have a specific name?

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > Microsoft Dynamics 365 | Integration, Dataverse, and general topics

#1
Martin Dráb Profile Picture

Martin Dráb 62 Most Valuable Professional

#2
#ManoVerse Profile Picture

#ManoVerse 57

#3
Pallavi Phade Profile Picture

Pallavi Phade 49

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans