2

I am new to Javascript and trying to run before I can walk but I have to produce a result so here I am.

I thought I had found the answer to this in another question but it did not work for me as expected, below is my script the function of which is to look at a SharePoint list and return some values into 3 arrays, I then use those arrays to provide data to complete some chart data.

                    <script>
                    // load all necessary sharepoint javascript libaries
                    SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {

                        // load the sharepoint list.
                        loadSharepointList();
                    });
                    var arrPlan = new Array()
                    var arrActual = new Array()
                    var arrMonth = new Array()


                    // loads the sharepoint list
                    function loadSharepointList() {

                        // create the sharepoint content.
                        var context = SP.ClientContext.get_current();

                        // get the list by the title.
                        var list = context.get_web().get_lists().getByTitle('Package');

                        // create the query.
                        var caml = new SP.CamlQuery();
                        caml.set_viewXml(''); 

                        // get the list items asynchronously
                        var listItems = list.getItems(caml);
                        context.load(listItems , 'Include(Title,Month,Plan,Actual)');
                        context.executeQueryAsync(

                            // success delegate
                            Function.createDelegate(this, function() {

                            // loop through the items.
                                var listEnumerator = listItems.getEnumerator();
                                while (listEnumerator.moveNext()) {

                                    // get the current list item.
                                    var listItem = listEnumerator.get_current();

                                    // get the field value.
                                    var titleValue = listItem.get_item('Month');
                                    var monthValue = listItem.get_item('Month');
                                    var planValue = listItem.get_item('Plan');
                                    var actualValue = listItem.get_item('Actual');
                                    //alert(monthValue);
                                    arrPlan.push(planValue);
                                    arrActual.push(actualValue);
                                    arrMonth.push(monthValue);
                                    //alert(arrMonth);

                                }

                            }),

                            // error delegate
                            Function.createDelegate(this, function() {
                                alert('Error fetching data from Sharepoint!');      
                            }));

                    }

                            //var labels = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October"];
                            var netpphcanvas = document.getElementById("pphchart");
                            var planData = {
                                label: 'Plan',
                                fill: false,
                                data: [1.06,1.58,1.74,1.62,1.50,1.37,1.36,1.44,1.84,1.76],
                                backgroundColor: 'rgba(133, 133, 133, 1)',
                                borderColor: 'rgba(133, 133, 133, 1)',
                                borderWidth: 3,
                                yAxisID: "y-axis-region"
                            };
                            var actualData = {
                                label: 'Actual',
                                fill: false,
                                data: [1.37,1.65,1.84, 1.78,1.55, 1.74,1.57, 1.74,1.90,1.63],
                                backgroundColor: 'rgba(99, 132, 0, 0.6)',
                                borderColor: 'rgba(99, 132, 0, 0.6)',
                                borderWidth: 3,
                                yAxisID: "y-axis-region"
                            };
                            //********This is the part I am using for testing
//***********
                            var netpphData = {
                                //labels: labels,
                                labels: arrMonth,
                                datasets: [planData,actualData]
                                            };
                            var netdelOptions = {
                            scales: {
                                xAxes: [{
                                    barPercentage: 1,
                                    categoryPercentage: 0.6
                                }],
                                yAxes: [{
                                    id: "y-axis-region"
                                }]
                            },
                            elements: {
                                line: {
                                    tension: 0, // disables bezier curves
                                }
                            },
                            title: {
                                display: true,
                                text: 'Net-Delivered PPH',
                                fontSize: 12
                            },
                            legend: {
                                display: true,
                                labels: {
                                    fontColor: '#000',
                                    fontSize: 12
                                }
                            }


                        };

                        var lineChart = new Chart(netpphcanvas, {
                            type: 'line',
                            data: netpphData,
                            options: netdelOptions
                        });
                    </script>

I am attempting to use the returned arrays to complete the Data and labels section of the chart, in order to test this I am starting with the monthly data, which is retrieved in this section of code...

context.executeQueryAsync(

                        // success delegate
                        Function.createDelegate(this, function() {

                        // loop through the items.
                            var listEnumerator = listItems.getEnumerator();
                            while (listEnumerator.moveNext()) {

                                // get the current list item.
                                var listItem = listEnumerator.get_current();

                                // get the field value.
                                var titleValue = listItem.get_item('Month');
                                var monthValue = listItem.get_item('Month');
                                var planValue = listItem.get_item('Plan');
                                var actualValue = listItem.get_item('Actual');
                                //alert(monthValue);
                                arrPlan.push(planValue);
                                arrActual.push(actualValue);
                                arrMonth.push(monthValue);
                                //alert(arrMonth);

                            }

                        }),

I have validated this works using the alert method and it does indeed return the months into the array called arrMonth

however, the rest of the script seems to run before this data source is accessed and the arrMonth is filled.

I have checked this also by using another array called labels and manually filing it and it works correctly.

I thought the reason for this was because the function to get the data was being called Asynchronously

context.executeQueryAsync(

however, I changed this to context.executeQuery( and still got the same result that the page loads before the data are retrieved

Clearly, I have missed something and I would appreciate any help

Kind regards Derek

ksav
  • 20,015
  • 6
  • 46
  • 66
Derek
  • 41
  • 1
  • 8

1 Answers1

1

You would need to chain promises to make sure all of this runs in sequence.

These two links will help you:

A synchronous Breeze ExecuteQuery

What does the function then() mean in JavaScript?

And this is a useful tutorial on promise chaining. https://javascript.info/promise-chaining

rf1234
  • 1,510
  • 12
  • 13
  • 1
    This is moving in the right direction for sure, seems the exact syntax is not the same which I think is due to me using SharePoint and the SPClientContext.Load method however the idea is the same, do this is it works and do this if it doesn't... Many thanks for your help! – Derek Nov 21 '18 at 13:51
  • I may have spoken to soon, I think my issue is actually when to call that process, what I mean is it will run the while statement to fill the array when the query is successful and still go on to try and use that array in the chart before the while has completed. How do I get the script to create the chart only to run after the while Loop has finished? – Derek Nov 21 '18 at 14:16
  • You need to put each step into a promise and chain those promises so that each step only gets executed after the previous has been completed. Here is a tutorial on promise chaining: https://javascript.info/promise-chaining – rf1234 Nov 21 '18 at 15:54
  • I'm getting nowhere with this now and just taking pot shots in the dark, is it possible some one could give me some direction using the code that I have – Derek Nov 27 '18 at 09:26