1

All,

I have some code that uses multiple variables, objects and arrays. Somehow my object which was filled is now empty.

var items = [];
var countryCode = "";
var message = "";
var dataset = {};
var countryData = {};
countryData.fillKey = 'NEW';

function getItems(url) {
$.ajax({
    url: _spPageContextInfo.webAbsoluteUrl + url,
    type: "GET",
    headers: {
        "accept": "application/json;odata=verbose",
    },
    success: function (data) {
             var items = data.d.results;
             for(var i = 0; i < items.length;i++) {
             countryCode = items[i].Country0.Column2;                         
             message = countryData.fillKey;
             dataset[countryCode] = message;
                          }
    },
    error: function (error) {
        alert(JSON.stringify(error));
    }
});
}

When I test dataset after this code it's empty. It should be something like:

dataset['UKR'] = countryData;
dataset['USA'] = countryData;
dataset['RUS'] = countryData;

Why doesn't this work?

Marco

My next code has to use the dataset:

var map = new Datamap({
    element: document.getElementById('container'),
    geographyConfig: {
            hideAntarctica: true,
            highlightFillColor: false,
            popupOnHover: true,
            highlightOnHover: false,
            borderColor: '#000000',
            borderWidth: 0.5
            },
            fills: {
                'NEW': '#FF0000',
                'OLD': '#FF7F7F',
                defaultFill: '#FFFED9' 
                      },
               data: dataset
                     });
            map.svg.call(d3.behavior.zoom().on("zoom", redraw));

function redraw() {
map.svg.selectAll("g").attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
            }

});
Marco
  • 85
  • 1
  • 14
  • You're making a web request so it's possible that the request hasn't completed by the time by the time you test the dataset. – Jason L Nov 09 '17 at 17:26
  • 1
    What is happening in this code that makes it 'not work'? What error? – jaswrks Nov 09 '17 at 17:27
  • ajax calls are asynchronous, javascript continues execution before the call completes. If you check the values of your dataset object right after the ajax call, it'll be empty because `success` hasn't fired yet. If you need to do something with your dataset just pass it as a parameter after creating it inside `success` – IrkenInvader Nov 09 '17 at 17:32
  • IrkenInvader, how can I pass it as a parameter? – Marco Nov 09 '17 at 17:38
  • My next code has to use the dataset: – Marco Nov 09 '17 at 17:39
  • Create a function that execute your next code and call it in the success callback. There is no workaround for that, it's just that it's asynchronous, so you have to execute your code AFTER the call has finished, hence inside the success callback in your case. – briosheje Nov 09 '17 at 17:40
  • So everything from var map = new Datamap({ onwards has to be inside the success call? – Marco Nov 09 '17 at 17:49

2 Answers2

0

You can pass a callback to the getItems function to call once the request is successful.

Here is a short example of a scenario where you need to get items, then do something with that data.

function processItems() {
  getItems('the/items/url', (dataset) => {
    var map = new Datamap({
      element: document.getElementById('container'),
      geographyConfig: {
        hideAntarctica: true,
        highlightFillColor: false,
        popupOnHover: true,
        highlightOnHover: false,
        borderColor: '#000000',
        borderWidth: 0.5
      },
      fills: {
        'NEW': '#FF0000',
        'OLD': '#FF7F7F',
        defaultFill: '#FFFED9'
      },
      data: dataset
    });
    map.svg.call(d3.behavior.zoom().on("zoom", redraw));

    function redraw() {
      map.svg.selectAll("g").attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
    }
  });
}


function getItems(url, callback) {
  $.ajax({
    url: _spPageContextInfo.webAbsoluteUrl + url,
    type: "GET",
    headers: {
      "accept": "application/json;odata=verbose",
    },
    success: function(data) {
      var items = data.d.results;
      for (var i = 0; i < items.length; i++) {
        countryCode = items[i].Country0.Column2;
        message = countryData.fillKey;
        dataset[countryCode] = message;
      }
      callback(dataset);
    },
    error: function(error) {
      alert(JSON.stringify(error));
    }
  });
}
IrkenInvader
  • 4,030
  • 1
  • 12
  • 23
  • thanks, does it matter in any way that the code is inside the $(document).ready(function () { – Marco Nov 09 '17 at 17:46
  • I don't think so, you can define functions inside of functions inside functions if you want to :) – IrkenInvader Nov 09 '17 at 17:49
  • someone suggested to put my next code inside the success function. Is that instead of the callback(dataset)? – Marco Nov 09 '17 at 17:51
  • You could put your next code inside the success function but it might get messy. The callback(dataset) lets you continue after the success function without making `success` too messy – IrkenInvader Nov 09 '17 at 17:55
  • IrkenInvader, could you post how that would look as I am not a pro :) – Marco Nov 09 '17 at 17:56
  • yeah I'll show you, I just saw you added your next code to the question – IrkenInvader Nov 09 '17 at 17:58
  • Yes sorry but I am a newbie trying to setup a SharePoint site. – Marco Nov 09 '17 at 17:59
  • Just to add another comment. When I place this `code` dataset['UKR'] = countryData; `code` before the var map = new Datamap({...... it works. – Marco Nov 09 '17 at 18:02
  • Something like that is what I was thinking. Replace `'the/items/url'` with the real url – IrkenInvader Nov 09 '17 at 18:09
  • Couldn't I just use 'url' which is declared before? `var urlForAllItems = "/_api/Web/Lists/GetByTitle('OIE Alerts')/Items?" + "$select=Title,Date_x0020_of_x0020_Event,Country0/Title,Country0/Column2&$expand=Country0&" + "$filter=Date_x0020_of_x0020_Event gt '"+startDate+"'&$orderby=Date_x0020_of_x0020_Event desc"; getItems(urlForAllItems);` – Marco Nov 09 '17 at 18:13
  • yep, the line would look like `getItems(urlForAllItems, (dataset) => {` – IrkenInvader Nov 09 '17 at 18:14
  • Is this code '=>'? – Marco Nov 09 '17 at 18:19
  • Yeah that is another way to write a function. Are you getting errors when you try it? – IrkenInvader Nov 09 '17 at 18:22
  • Nope, I can't test the code as I don't have sharePoint at home :( – Marco Nov 09 '17 at 18:23
  • IrkenInvader, I tested the code an indeed I get a syntax error at (dataset) => { – Marco Nov 10 '17 at 11:03
  • Changed the code: `function processItems() { getItems(urlForAllItems, function(dataset) { var map = new Datamap({ element: document.getElementById('container'), geographyConfig: { hideAntarctica: true, highlightFillColor: false, popupOnHover: true, highlightOnHover: false, borderColor: '#000000',....' Also added the variables which were left out: 'var items = []; var countryCode = ""; var message = ""; var dataset = {}; var countryData = {}; countryData.fillKey = 'NEW';` Still not working. No errors. – Marco Nov 10 '17 at 11:38
0

So I solved it. Sometimes things are right in front of you but you don't see it. Just needed to set async to FALSE.

function getItems(url) {
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + url,
type: "GET",
async: false,
headers: {
    "accept": "application/json;odata=verbose",
},
success: function (data) {
         var items = data.d.results;
         for(var i = 0; i < items.length;i++) {
         countryCode = items[i].Country0.Column2;                         
         message = countryData.fillKey;
         dataset[countryCode] = message;
                      }
},
error: function (error) {
    alert(JSON.stringify(error));
}
});
}
Marco
  • 85
  • 1
  • 14