0

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 ?

1

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();
  • Thanks for the help Bhaskar. I tried the code that you have suggested. While debugging in the chrome console I found that It goes into the 2nd function correctly, but it doesn't goes into the success of 2nd function which in turn doesn't populate the array and after the success of the first is executed it goes into the success of the second to get officeId. – RBK Sep 18 '18 at 5:34
  • Check your 'getOfficeId' function. Parameter passed 'myId' is not used anywhere. Also its looping all items from 'Second List' and hence all 'Title' values are getting resolved. Just check your code so that it should return single value. – Bhaskar Dhone Sep 18 '18 at 6:08
  • Means the CAML query must return only one value ? As I am getting multiple values through present CAML Query. – RBK Sep 18 '18 at 6:16
  • Yes , if you want to return single value. If you want to return array , in that you have to form an array and push all values [Office Ids] to array and then return it. – Bhaskar Dhone Sep 18 '18 at 6:17
  • Then how can I write CAML query to count number of title which equals myId which has been passed as a parameter ? – RBK Sep 18 '18 at 6:19
0

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');        
    });
}
0

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 :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.