I have a MainController that loads an array of Objects via RestAngular
controllers.controller('MainController', $scope, Restangular) {
$scope.colors = {};
Restangular.all('colors').getList().then(function(colors) {
angular.forEach(colors, function(c) {
c.brightness = getBrightness(c);
$scope.colors[c.id] = c;
});
});
};
And I have a routing to have a sub-page for dealing with colors.
$stateProvider
.state('picture', {
abstract: true,
url: "/picture/{pictureId:[0-9]{1,6}}",
templateUrl: "partials/picture.html",
controller: 'MainController'
}
)
.state('picture.colors', {
url: "/colors",
templateUrl: "partials/picture_colors.html",
controller: 'PictureColorsController'
}
);
Here, I want to have a drop-down menu to multi-select colors.
<multiselect ng-model="selector.colors"
options="c as c.name for c in colors| orderBy:'brightness'"
data-multiple="true"
header="Colors">
</multiselect>
This works well. But when the page is loaded, I want all colors to be selected. So what I want is this:
controllers.controller('PictureColorsController', $scope) {
$scope.selector = {colors:[]};
var selectAll = function() {
$scope.selector.colors.splice(0, $scope.selector.colors.length);
angular.forEach($scope.colors, function(c) {
$scope.selector.colors.push(c);
});
};
selectAll();
};
But at the time the the child controller 'PictureColorController' is executed, the colors aren't loaded yet. So the only solution I can think of is following, but I don't really like it. It feels like I'm doing something wrong.
controllers.controller('MainController', $scope, Restangular) {
$scope.colors = {};
var colorsCallback = undefined;
$scope.registerColorsCallbackFn = function(func) {
colorsCallback = func;
};
Restangular.all('colors').getList().then(function(colors) {
angular.forEach(colors, function(c) {
c.brightness = getBrightness(c);
$scope.colors[c.id] = c;
});
if (colorsCallback) {
colorsCallback();
}
});
};
and
controllers.controller('PictureColorsController', $scope) {
$scope.selector = {colors:[]};
var selectAll = function() {
$scope.selector.colors.splice(0, $scope.selector.colors.length);
angular.forEach($scope.colors, function(c) {
$scope.selector.colors.push(c);
});
};
selectAll();
$scope.registerColorsCallbackFn(selectAll);
};
Is there a cleaner way to do this? There are several lists of data that I want to load in my MainController that all need to be loaded before I want to execute any of the child controllers. Is there a good mechanism for that?
You can use ui-router's resolve property on the state:
.state('picture.colors', {
url: "/colors",
templateUrl: "partials/picture_colors.html",
controller: 'PictureColorsController'
},
resolve: {
colors: function(Restangular) {
return Restangular.all('colors').getList();
}
}
)
ui-router will resolve every promise in the resolve object before executing your controller. And it'll give you a colors
parameter you can inject in your controller with the data that the promise resolves with.
There's not necessarily anything wrong with your approach, though. A slightly more structured version is one of the approaches in John Papa's Angular style guide.