MikeyM MikeyM - 5 months ago 31
JSON Question

ngHandsontable loading dynamic data into dropdown or autocomplete fields

I'm trying to load ngHandsontable dropdown and autocorrect controls from a service call that returns a promise. When I load these controls from static data, they work fine, but when I attempt to load them from an async call the controls are empty.

This plunker http://embed.plnkr.co/DQKBZK/ has one example table that works fine. It's loaded with static arrays. The second table is able to load data for the table rows from a promise, but I can't get the dropdown or autocomplete controls to load anything this way. I would appreciate any advice or suggestions you can offer. Code snippets:

In the template, both tables look similar, this is the dynamic one:

<hot-table datarows="dctrl.dynamicData" settings="dctrl.dynamicSettings">
<hot-column type="text" title="'Id'" data="myid"></hot-column>
<hot-column source="dctrl.dynamicWeather" type="'dropdown'" title="'Weather'" data="weather"></hot-column>
<hot-column type="'autocomplete'" title="'Menu'" data="menu">
<hot-autocomplete datarows="{{dctrl.dynamicMenu}}"></hot-autocomplete>
</hot-column>
</hot-table>


The controller loads the first table and controls using static data provided by a service:

vm.staticData = DemoService.staticData;
vm.staticWeather = DemoService.staticWeather;
vm.staticMenu = DemoService.staticMenu;


The static data provided by the service:

staticData: [
{"myid": "1", "weather": "Cloudy", "menu": "Cheese"},
{"myid": "2", "weather": "Sunny", "menu": "Turnips"}
],
staticWeather: ['Cloudy', 'Sunny', 'Rainy'], // dropdown
staticMenu: ['Beans', 'Cheese', 'Turnips'].join(','), // autocomplete


The dynamic data is provided by simple JSON files via service calls. So for the weather dropdown, we have this in the controller:

vm.dynamicWeather = [];

DemoService.getDynamicWeather()
.then(function successCallback(results) {
vm.dynamicWeather = results;
});


Here's how the dynamic weather data is provided by the service:

getDynamicWeather: function() {
var def = $q.defer();
$http.get('weather.json')
.then(function successCallback(response) {
var i, responseArray = [];
for (i = 0; i < response.data.length; i++) {
responseArray.push(response.data[i].weather);
}
def.resolve(responseArray);
});
return def.promise;
},


And the JSON weather data file:

[
{"weather": "Cloudy"},
{"weather": "Sunny"},
{"weather": "Rainy"}
]


I've been thrashing about with this thing for a while now, without much success. Things I've tried include placing calls in a $timeout (to trigger a digest cycle), getting an instance of the handsontable and forcing a render, using objects instead of arrays, and using a function call to load the dropdown data. I've variously succeeded in loading data twice, or not at all, or (with the function call) getting handsontable into an endless loop that crashes the browser. Any suggestions you can offer will be appreciated, thanks.

Answer

It's definitely possible to add values after the table has been instantiated:

<button ng-click="dctrl.staticWeather.push('123')">Add data</button>
<div>{{x}} {{dctrl.staticWeather}}</div>

I'd suggest using the pattern that the angular $resource service uses: - Declare an empty array in the load function - In the $http promise, copy the resolved data to the previously allocated array - return the array before the promise is resolved

Setup: vm.dynamicWeather = DemoService.getDynamicWeather();

and:

    getDynamicWeather: function() {
     var responseArray = [];

    $http.get('weather.json')
      .then(function successCallback(response) {
        var i;
        for (i = 0; i < response.data.length; i++) {
          responseArray.push(response.data[i].weather);
        }
      });
      return responseArray;
  }
Comments