Skip to main content

Notifications

Announcements

No record found.

Dynamics 365 general forum
Answered

Check the length of an Array of entities in JavaScript

Posted on by 355

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?

  • Verified answer
    a33ik Profile Picture
    a33ik 84,321 Most Valuable Professional on at
    RE: Check the length of an Array of entities in JavaScript

    You can use following code:

    if (typeof (PREFIX) == "undefined") {

       PREFIX = { __namespace: true };

    }

    if (typeof (PREFIX.collection) == "undefined") {

       PREFIX.collection = { __namespace: true };

    }

    PREFIX.collection.Ribbon = (function () {

      function onLoad(executionContext){

          // some logic here

      }

       function myFunction_OnClick(executionContext) {

           // some logic here

       }

       return {

         myFunction_OnClick: myFunction_OnClick,

         onLoad: onLoad

       };

    })();

  • Joel D Profile Picture
    Joel D 355 on at
    RE: Check the length of an Array of entities in JavaScript

    Ok, thanks.

    I have another doubt. I would like to have another function with the same namespace, it's an OnLoad function that will be associated to the entity form (not to ribbon button), may I put it inside the same PREFIX.collection.Ribbon function, as in the following?

    if (typeof (PREFIX) == "undefined") {
        PREFIX = { __namespace: true };
    }
    if (typeof (PREFIX.collection) == "undefined") {
        PREFIX.collection = { __namespace: true };
    }
    
    
    
    PREFIX.collection.Ribbon = (function () {
    
       function onLoad(executionContext){
           // some logic here
       };
       
    
        function myFunction_OnClick(executionContext) {
            // some logic here
        };
        
        
        return {
    	myFunction_OnClick: myFunction_OnClick
        };
    })();

    And then I would add the PREFIX.collection.Ribbon.onLoad to the OnLoad event handler in the entity form properties, would it be correct? -->

    7510.Conflicts.png

  • Verified answer
    a33ik Profile Picture
    a33ik 84,321 Most Valuable Professional on at
    RE: Check the length of an Array of entities in JavaScript

    Hello,

    The way I wrote the code is the typical way to have "private" if you would functions and allow exposing only those pieces that are required. The return statement on line 41 is used to return and expose that myFunction_OnClick "internal" function as a function under "PREFIX.collection.Ribbon namespace.

    Here is why your spinner did not work you can define few functions hoping it will call it sequenty - you have to wrap it inside another function:

    function success (result){

         Xrm.Utility.closeProgressIndicator();  // line 34

         resolve(result.entities);

    },

    function (e) {

    Xrm.Utility.closeProgressIndicator();        //line 36

    reject(e);

    });

  • Joel D Profile Picture
    Joel D 355 on at
    RE: Check the length of an Array of entities in JavaScript

    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?

  • Verified answer
    a33ik Profile Picture
    a33ik 84,321 Most Valuable Professional on at
    RE: Check the length of an Array of entities in JavaScript

    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
    Joel D 355 on at
    RE: Check the length of an Array of entities in JavaScript



    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 )

  • a33ik Profile Picture
    a33ik 84,321 Most Valuable Professional on at
    RE: Check the length of an Array of entities in JavaScript

    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
    Joel D 355 on at
    RE: Check the length of an Array of entities in JavaScript

    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");
    };

  • Suggested answer
    a33ik Profile Picture
    a33ik 84,321 Most Valuable Professional on at
    RE: Check the length of an Array of entities in JavaScript

    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
    Joel D 355 on at
    RE: Check the length of an Array of entities in JavaScript

    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;
    }

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

Anton Venter – Community Spotlight

Kudos to our October Community Star of the month!

Announcing Our 2024 Season 2 Super Users!

A new season of Super Users has arrived, and we are so grateful for the daily…

Dynamics 365 Community Newsletter - September 2024

Check out the latest community news

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 290,564 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 228,651 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,148

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans
Liquid error: parsing "/forums/thread/details/?threadid=%27nvOpzp;%20AND%201=1%20OR%20(%3C%27%22%3EiKO))," - Too many )'s.