Reputation: 41
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
Upvotes: 2
Views: 638
Reputation: 1605
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
Upvotes: 1