Reputation: 969
I am using ui-grid with AngularJS (and MySQL at backend) for a project. I got a table which gets its data from MySQL database. Its rows (or cells) are editable (as mentioned in this example on ui-grid website). One column of the table has dropdown. Dropdown is working perfectly with hard coded data as described in that example. I want to populate it from database but it shows empty dropdown list everytime I tried.
Fetching of data from database is done by service which is injected into the controller with intention to run the code that gets data from database (i.e. $http.get('/some/route')) so that we have all the data for table rows and dropdown list in hand before or at the time of page loading.
But the variable (sitesD) that gets data for dropdown when printed, shows it is undefined.
Here is the controller:
angular.module('WorkersCtrl', []).controller('WorkersController', function($scope, $http, serverData) {
$scope.gridOptions = {enableHorizontalScrollbar: 1};
/* getting rows from databse by using "serverData" custom service */
serverData.getData().then(function(response) {
$scope.gridOptions.data = response.data[0];
$scope.sitesData = response.data[1];
});
var sitesD = $scope.sitesData;
$scope.gridOptions.columnDefs = [
{ field: 'first_name', width:150, enableCellEdit: true},
{ field: 'last_name', width:150},
{ field: 'father_first_name', width:150},
{ field: 'father_last_name', width:150},
{ field: 'mother_first_name', width:150},
{ field: 'mother_last_name', width:150},
{ field: 'sex', width:50, editableCellTemplate: 'ui-grid/dropdownEditor',
editDropdownValueLabel: 'gender', editDropdownOptionsArray: [
{ id: 'M', gender: 'Male' },
{ id: 'F', gender: 'Female' }]},
{ field: 'address', width:250},
{ field: 'phone', width:100, type: 'number'},
{ field: 'date_of_birth', width:150, type: 'date', cellFilter: 'date:"yyyy-MM-dd"'},
{ field: 'post_code', displayName: 'Post', width:50},
{ field: 'joining_date', width:150, type: 'date', cellFilter: 'date:"yyyy-MM-dd"'},
{ field: 'rate', width:50, type: 'number'},
{ field: 'site_name', width:150, editableCellTemplate: 'ui-grid/dropdownEditor',
editDropdownIdLabel:'site_id', editDropdownValueLabel: 'site_name', editDropdownOptionsArray: sitesD },
];
alert(sitesD); //checking the variable value: it shows undefined.
$scope.gridOptions.onRegisterApi = function(gridApi){
$scope.gridApi = gridApi;
};
$scope.addData = function() {
$scope.gridOptions.data.push({
'first_name': '',
'last_name': '',
'father_first_name': '',
'father_last_name': '',
'mother_first_name': '',
'mother_last_name': '',
'sex': '',
'address': '',
'phone': '',
'date_of_birth': '',
'post_code': '',
'joining_date': '',
'rate': '',
'site_name': ''
});
};
});
Code of service is following:
angular.module('GeekService', []).factory('serverData', ['$http', function($http) {
return {
getData: function() {
return $http.get('/workers')
}
}
}]);
Here is the screenshot of page when alert(sitesD);
runs:
What I understand is variable gets value after the page loads and so the editDropdownOptionsArray
gets no value for dropdown.
All these are assumptions I made while looking for solution but haven't sceeded yet. Please help me. I feel I am even didn't understand where's the problem.
Feel free to ask further information if needed.
PS: While writing the question I found there is version incompatibility between my Angular and ui-grid. ui-grid 3.x is compatible with Angular's 1.4.x but I'm using ui-grid 3.x with Angular 1.5.5. Is it can be the reason?
EDIT: Here is the screenshot, showing how the dropdown looks:
Upvotes: 1
Views: 3446
Reputation: 1912
Harmanpreet,
Since you are bringing in dynamic content asynchronously I would recommend looking at the ui-grid "editDropdownRowEntityOptionsArrayPath" functionality instead of "editDropdownOptionsArray" as that functionality appears to be meant for static values as you are discovering now. There is information on this on the UI-grid API site: http://ui-grid.info/docs/#/api/ui.grid.edit.api:ColumnDef
If the data is a static list and won't be changing or dependent then maybe the code below would work as well, thanks for reaching out:
serverData.getData().then(function(response) {
$scope.gridOptions.data = response.data[0];
$scope.sitesData = response.data[1];
// You may have to shape data in a method before doing the next line
// ex: var sitesArray = shapeSitesData();
$scope.gridOptions.columnDefs[13].editDropdownOptionsArray = $scope.sitesData;
});
Since Stackoverflow doesn't respect new people's opinions I cannot comment on your thread with transistor. Hopefully you see this as I believe it will help. The issue you are encountering could also be due to the fact that ui-grid doesn't do a great job of mapping ids and values. You should try my variant (which i believe improves upon @mltroutt's solution).
angular.module('app')
.controller('yourctrl', yourFunction)
.filter('griddropdown', function () {
return function (input, context) {
var fieldLevel = (context.editDropdownOptionsArray == undefined) ? context.col.colDef : context;
var map = fieldLevel.editDropdownOptionsArray;
var idField = fieldLevel.editDropdownIdLabel;
var valueField = fieldLevel.editDropdownValueLabel;
var initial = context.row.entity[context.col.field];
if (typeof map !== "undefined") {
for (var i = 0; i < map.length; i++) {
if (map[i][idField] == input) {
return map[i][valueField];
}
}
}
else if (initial) {
return initial;
}
return input;
};
Then add this to your coldef
cellFilter: 'griddropdown:this'
Upvotes: 3
Reputation: 2925
It's a timing issue. At the point where you're calling alert(sitesD)
, your data hasn't loaded yet. Angular promises are asynchronous, which is what the then
statement is for.
If you move your alert inside the then
, your dropdown data should appear:
serverData.getData().then(function(response) {
$scope.gridOptions.data = response.data[0];
$scope.sitesData = response.data[1];
alert($scope.sitesData);
});
If it's still undefined, either response.data[1] doesn't contain your data, or you've got a problem with your server-side logic.
If your data does appear correctly in the then
alert, next try changing editDropdownOptionsArray: $scope.sitesData
Edit: in my solution, I use an angular-resource instead of $http, and it works as described above. You may want to try this, though I'd expect it to work the way you've coded it with $http as well.
angular.module('siteDataService', ['ngResource'])
.factory('siteData', function($resource) {
return $resource('/workers', {}, {
query: { method:'GET', isArray: true }
}
});
Make sure you include angular-resource.js
in your HTML, and take a dependency on siteDataService
in your application, and add siteData
in your controller.
To run the query, you'd use $scope.serverResponse = siteData.query();
in the body of your controller.
Upvotes: 0