Question

I am able to fetch single SharePoint List using JavaScript. But here I need to Query other list based on the value fetched from first list. I have also used angularjs for the page.

Find the below JavaScript code for the reference.

table_caption.controller("myTableController", function($scope) {
var context;
    var web;
    var myList;
    var camlQuery;
    var colListItem;

// calling the getData function
    getData();

//This is getData() function
    function getData(){
        context = new SP.ClientContext("https://mymysite/sites/example");
        web = context.get_web();
        myList = web.get_lists().getByTitle('My Data');
        camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml("<View><RowLimit>500</RowLimit></View>");
        colListItem =  myList.getItems(camlQuery);
        context.load(myList);
        context.load(colListItem);
        context.executeQueryAsync(ongetAllInfo, onAllInfoFailed);
    }

    //success function
    function ongetAllInfo(){
        var resultItems = [];
        var listItemEnumerator = colListItem.getEnumerator();
        while(listItemEnumerator.moveNext()){
            var oListItem = listItemEnumerator.get_current();
            var resultItem = {};
            resultItem['fN'] = oListItem.get_item('firstName').toString();
            resultItem['lN'] = oListItem.get_item('lastName').toString();
            resultItem['birDate'] = oListItem.get_item('birthDate').toDateString();

            // Need to call the other function here so that I can get the officeId from other function based on the firstName and put in the resultItem.
            resultItem['officeId'] = getOfficeId(oListItem.get_item('firstName').toString())

            resultItems.push(resultItem);
        }
        $scope.info = resultItems;
        $scope.keys = Object.keys($scope.info[0]);
    }

    //error function
    function onAllInfoFailed(){
        alert("Failed to retrieve your data. Try again after sometime.");
    }
});

Here is my other function that needs to be called.

function getOfficeId(myId){
    var myMainId = myId;
    var myTrainingCount = [];
    var context = new SP.ClientContext("https://mymysite/sites/example");
    var web = context.get_web();
    var myList = web.get_lists().getByTitle('Second List');
    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml("<View><Query><OrderBy><FieldRef Name='Title'/></OrderBy></Query></View>");
    var colListItem =  myList.getItems(camlQuery);
    context.load(myList);
    context.load(colListItem);
    context.executeQueryAsync(function(){
        var listItemEnumerator = result.getEnumerator();
        while(listItemEnumerator.moveNext()){
            var oListItem = listItemEnumerator.get_current();
            var office_id = oListItem.get_item('Title');    
        }
    },function(sender,args){
            alert('Failed to retrieve nominations');        
    });
}

The problem here is that my getData function gets executed without getting the officeId from other list. I know that this is causing due to asynchronous calls.

But how can I wait till the other function return the value ?

Was it helpful?

Solution

you can user Promises/deferreds in order to make it async. Change your getOfficeId function as below

    function getOfficeId(myId,oListItem){
    var resultItem = {};
    resultItem['fN'] = oListItem.get_item('firstName').toString();
    resultItem['lN'] = oListItem.get_item('lastName').toString();
    resultItem['birDate'] = oListItem.get_item('birthDate').toDateString();
    var deferred = $.Deferred();
    var myMainId = myId;
    var myTrainingCount = [];
    var context = new SP.ClientContext("https://yoursite.sharepoint.com/sites/yoursite");
    var web = context.get_web();
    var myList = web.get_lists().getByTitle('Second List');
    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml("<View><Query><OrderBy><FieldRef Name='Title'/></OrderBy></Query></View>");
    var colListItem =  myList.getItems(camlQuery);
    context.load(myList);
    context.load(colListItem);
    context.executeQueryAsync(function(){
        var listItemEnumerator = colListItem.getEnumerator();
         var i = 0; 
        while(listItemEnumerator.moveNext()){ 
        var oListItem = listItemEnumerator.get_current(); 
        var office_id = oListItem.get_item('Title'); 
        if( office_id == myId ) 
        { 
        i++ 
        } 
        }
        resultItem['officeId']=i;
        deferred.resolve(resultItem);
    },function(sender,args){
            deferred.reject(sender, args);
            alert('Failed to retrieve nominations');        
    });
    return deferred.promise();
}

and while retrieving office id change below line

resultItem['officeId'] = getOfficeId(oListItem.get_item('firstName').toString())

with below code

        getOfficeId(oListItem.get_item('firstName').toString(),oListItem).then(
        function (officeId) {
            resultItems.push(officeId);
        },
        function (sender, args) {
            alert(args.get_message());
        }
    ); 

This will wait till function return value and then assign that value and then push it to array.

Comment out below lines from your ongetAllInfo() function as we moved those lines to getOfficeId() function which will return array.

var resultItem = {};
resultItem['fN'] = oListItem.get_item('firstName').toString();
resultItem['lN'] = oListItem.get_item('lastName').toString();
resultItem['birDate'] = oListItem.get_item('birthDate').toDateString();

OTHER TIPS

Thanks Bhaskar for the help.

Based on the Bhaskar's suggestion developed the below code.

This is main controller.Firstly I just updated my array with required details and passed as parameter to the second function.

Then in the second function where I looped my array to check if first name is available or not. If yes then it will increase the count and update the array Item.

After all updates, it will then fill my angular js table.

table_caption.controller("myTableController", function($scope) {
var context;
    var web;
    var myList;
    var camlQuery;
    var colListItem;

// calling the getData function
    getData();

//This is getData() function
    function getData(){
        context = new SP.ClientContext("https://mymysite/sites/example");
        web = context.get_web();
        myList = web.get_lists().getByTitle('My Data');
        camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml("<View><RowLimit>500</RowLimit></View>");
        colListItem =  myList.getItems(camlQuery);
        context.load(myList);
        context.load(colListItem);
        context.executeQueryAsync(ongetAllInfo, onAllInfoFailed);
    }

    //success function
    function ongetAllInfo(){
        var resultItems = [];
        var listItemEnumerator = colListItem.getEnumerator();
        while(listItemEnumerator.moveNext()){
            var oListItem = listItemEnumerator.get_current();
            var resultItem = {};
            resultItem['fN'] = oListItem.get_item('firstName').toString();
            resultItem['lN'] = oListItem.get_item('lastName').toString();
            resultItem['birDate'] = oListItem.get_item('birthDate').toDateString();
            resultItem['officeCount'] = 0;    
            resultItems.push(resultItem);
        }
        // called the second function here.
        getOfficeId(resultItems);
    }

    //error function
    function onAllInfoFailed(){
        alert("Failed to retrieve your data. Try again after sometime.");
    }
});

This is the second function.

function getOfficeId(resultItems){
    var myMainId = myId;
    var myTrainingCount = [];
    var context = new SP.ClientContext("https://mymysite/sites/example");
    var web = context.get_web();
    var myList = web.get_lists().getByTitle('Second List');
    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml("<View><Query><OrderBy><FieldRef Name='Title'/></OrderBy></Query></View>");
    var colListItem =  myList.getItems(camlQuery);
    context.load(myList);
    context.load(colListItem);
    context.executeQueryAsync(function(){
        var officeCount = 0;
        var listItemEnumerator = result.getEnumerator();
        while(listItemEnumerator.moveNext()){
         for(i=0;i<resultItems.length;i++){
            var oListItem = listItemEnumerator.get_current();
            if(oListItem.get_item('Title').toString === resultItems['fN']){
               resultItem['officeCount'] = resultItem['officeCount'] + 1;
            }    
         }
        }
        $scope.info = resultItems;
        $scope.keys = Object.keys($scope.info[0]);
    },function(sender,args){
            alert('Failed to retrieve nominations');        
    });
}

The better solution I found out using the jQuery chaining mechanism which gave me the result using deferred.

Here is the stack overflow post that helped me out:- Chaining jQuery Deferred.

So the following code will be as follows.

Main Angular js controller

table_caption.controller("myTableController", function($scope,$http,$timeout) {

var myData = getData($timeout);
    var myData2 = myData.then(function(res){
        return getOfficeId(res,$timeout);
    });
    var myListItems = myData2.then(function(listItems){
        return listItems;
    });

    myListItems.done(function(listItems){
        $scope.info = listItems;
        $scope.keys = Object.keys($scope.info[0]);
    });

}

getData function()

function getData(){
        context = new SP.ClientContext("https://mymysite/sites/example");
        var deferred = &.Deferred();
        web = context.get_web();
        myList = web.get_lists().getByTitle('My Data');
        camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml("<View><RowLimit>500</RowLimit></View>");
        colListItem =  myList.getItems(camlQuery);
        context.load(myList);
        context.load(colListItem);
        context.executeQueryAsync(function(){
            var listItemEnumerator = colListItem.getEnumerator();
            $timeout(function(){return deferred.resolve(listItemEnumerator)});
        }, function(){
            return deferred.reject(args.get_message());
        });
        return deferred.promise();
    }   

getOfficeId function()

function getOfficeId(res,$timeout){
    var myMainId = myId;
    var deferred = $.Deferred();
    var resultItems = [];
    var myTrainingCount = [];
    var context = new SP.ClientContext("https://mymysite/sites/example");
    var web = context.get_web();
    var myList = web.get_lists().getByTitle('Second List');
    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml("<View><Query><OrderBy><FieldRef Name='Title'/></OrderBy></Query></View>");
    var colListItem =  myList.getItems(camlQuery);
    context.load(myList);
    context.load(colListItem);
    context.executeQueryAsync(function(){
        while(res.moveNext()){
                var oResultItem = res.get_current();
                var newlistItemEnumerator = colListItem.getEnumerator();
                var total_count = 0;
                var isRegistered = 'false';                             
                var resultItem = {};
                while(newlistItemEnumerator.moveNext()){
                    var newoListItem = newlistItemEnumerator.get_current();
                        if(newoListItem.get_item('firstName').toString === oResultItem.get_item('fN').toString()){
                           resultItem['officeCount'] = resultItem['officeCount'] + 1;
                        } 
                }
            resultItem['fN'] = oResultItem.get_item('firstName').toString();
            resultItem['lN'] = oResultItem.get_item('lastName').toString();
            resultItem['birDate'] = oResultItem.get_item('birthDate').toDateString();
            resultItems.push(resultItem);
        }
        $timeout(function(){return deferred.resolve(resultItems)},3000);
    },function(sender,args){
            return deferred.reject(args[0]);        
    });
   return deferred.promise();
}

for explaination how this works you can look the link of website given below.

jQuery chaining with deferred explaination

Hope this post helps someone in future :)

Licensed under: CC-BY-SA with attribution
Not affiliated with sharepoint.stackexchange
scroll top