callback for beginning of controller work - angularjs

I have two controllers
angular.module('myApp.controllers', [])
.controller('Controller1',function(){
getController1();
})
.controller('Controller2',function(){
getController2();
})
I have some $http function in service with GET:
.service("geInfo", function() {
})
I want that my controllers will start only when i get the data of the service.
Do i have to use $q (promise), $watch or something else?
Does somebody can provide example?
Thanks!

You must resolve it in configuration phase:
(function() {
'use strict';
angular
.module('dashboardApp', [
'ngRoute'
])
.config(config);
/* #ngInject */
function config($routeProvider) {
$routeProvider
.when("/youUrl", {
templateUrl: "youtTemplate.html",
controller: "yourController",
resolve: {
initInfo: function(infoService){
return infoService.getInfo();
}
}
});
}
})();
Now you have initInfo in your controller:
.controller('Controller2',function($scope, initInfo){
$scope.info = initInfo;
})
By this way the router wont load the view until your service return initInfo.

Related

AngularJS - problems when using resolve

I basically need to call a server that's will return me a JSON structure before load the controller.
I was using many methods to archive that, but it's not working. It's don't show me any error and the page got blank. Any clue about what's going on ?
This is my controller..
angular
.module('app',[
'ngAnimate',
'ui.router',
'ui.bootstrap',
'ngCookies'
])
.run(function($rootScope) {
$rootScope.backendServer = "http://localhost:5000/";
})
.config(['$urlRouterProvider','$stateProvider', function($urlRouterProvider,$stateProvider) {
$stateProvider
.state('cms',{
url: '/my',
templateUrl: './app/templates/my.html',
controller : 'my',
resolve: {
dbState: function ($q) {
var defer = $q.defer();
Database.check().then(function (s) {
defer.resolve(s);
});
return defer.promise;
}
}
})
}])
.controller(function ($scope){
})
...and this is my service:
angular
.module('app')
.factory('Database',['$http', '$rootScope','$q', function($http, $rootScope, $q) {
return {
check: function () {
var call = $rootScope.backendServer + 'cms/database/check';
return $http.get(call);
}
}
}]);
don't create a defer object when you already returning a promise. so remove the defer and just return the factory function
also, inject the Database service to resolve
resolve: {
dbState: function(Database) {
return Database.check()
}
}
In the controller catch it like this
.controller("ctrl", function($scope, dbState) {
console.log(dbState.data)
})
Demo

Using angular routeProvider with controller

Please consider the this code where the routeProvider is needed to inject page(n).html in ng-view.
In addition to the console error:
unknown provider: $routeProviderProvider <- $routeProvider
The argument to function routeIt is the name of the page to navigate to, How can I mix a conditional switch with routeProvider.when in order to call the page matching the argument in the most efficient manner? Thanks
(function () {
'use strict';
angular
.module('appModule')
.controller('MainMenuCtrl', ['$scope', '$http', 'TogglerFactory', '$routeProvider', MainMenuCtrl]);
function MainMenuCtrl($scope, $http, Toggler, routeProvider) {
$http.get('models/mainMenu.json').then(
function (response) {
$scope.menuItems = response.data;
},
function (error) {
alert("http error");
}
)
function routeIt (page) {
routeProvider
.when('/page1', {
url: "/page1",
templateUrl: 'views/page1.html',
controller: 'Page1Ctrl'
})
.when('/page2', {
url: "/page2",
templateUrl: 'views/page2.html',
controller: 'Page2Ctrl'
})
}
$scope.itemClicked = function (item){
Toggler.menuToggle();
routeIt(item);
}
}
})();
Service providers aren't available for injection in run phase (i.e. anywhere but provider services and config blocks). It is possible to make route provider injectable and configure it after config phase,
app.config(function ($provide, $routeProvider) {
$provide.value('$routeProvider', $routeProvider);
});
And controllers aren't the best places to implement any logic (e.g. route hot-plug).
Ok you're using your routeProvider wrong you need to configure your routes inside .config blocks
angular.module('myApp', [])
.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/page1', {
url: "/page1",
templateUrl: 'views/page1.html',
controller: 'Page1Ctrl'
}
})
If you want to change the url from your controller use $location.path('/page1'); inside your controller.

How to pass initialization data to angular module?

I have a webmethod on my remote server returning a JSon object.
Said json object contains strings which are required for the module to proper work.
So, is there a way to pass something to an angular module?
An idea could be to perform an http request inside of the initialization of the module:
$scope.init = function(){
$http.get ()
...
then(){
$scope.mydata = result;
}
};
But that would be asynchronous...
If you are worried about the async nature of an HTTP request to fill out your $scope.mydata variable, then you need to include this in a RESOLVE in your route.
I'm using UI-ROUTER in my current project:
(function() {
'use strict';
angular
.module('capps.core')
.config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home.capps', {
url: '/',
template: '<ui-view/>',
data: {
requireLogin: true
},
resolve:{
resolveFunction: resolveFunction
}
});
}
]);
resolveFunction['$inject'] = ['$http'];
function resolveFunction($http) {
return $http.get(API_URL)
.then(function(res) {
console.log(res);
});
}
})();
Then in your controller, you can pass 'resolveFunction' as a dependency... then use that to assign to your $scope.myData.
...
angular.controller('myController', myController);
myController.$inject = ['resolveFunction', '$scope'];
function myController(resolveFunction, $scope) {
$scope.mydata = resolveFunction.data;
console.log(mydata);
};

How to inject an external factory provider in angular config?

I'm trying to inject a factory provider from another js file but it can't locate the provider. If this can't be done, what is the better way?
demo.config.js
function configState($stateProvider, $urlRouterProvider, $compileProvider, demoProvider) {
// Optimize load start with remove binding information inside the DOM element
$compileProvider.debugInfoEnabled(true);
// Set default state
$urlRouterProvider.otherwise("/dashboard");
$stateProvider
// Dashboard - Main page
.state('dashboard', {
url: "/dashboard",
templateUrl: "views/dashboard.html",
data: {
pageTitle: 'Dashboard',
}
})
}
angular
.module('demoApp')
.config(configState)
.run(function($rootScope, $state) {
$rootScope.$state = $state;
});
demo.provider.js
(function () {
'use strict';
angular
.module('demoApp')
.provider('demo', function() {
return {
$get: function() {
return {
title: "Starcraft"
}
}
}
});
})();
I always put my own provider to controllers. Like in my directive
(function() {
'use strict';
angular.module('yourMod').directive('yourViewPage', yourViewPage);
angular.module('yourMod').controller('YourViewPageCtrl', YourViewPageCtrl);
function YourViewPageCtrl(YourProvider) {
//your code!!!
// Example YourProvider.getSomeThing();
console.log('My life for Aiur!!!');
}
})();

Angularjs resolve with controller as string

My style of writing angular controllers is like this (using controller name instead of function)
angular.module('mymodule', [
])
.controller('myController', [
'$scope',
function($scope) {
// Some code here
}
]);
What I need now is when providing i routes I want to define resolve part:
$routeProvider.when('/someroute', {
templateUrl: 'partials/someroute.html',
resolve: myController.resolve}) // THIS IS THE CRITICAL LINE
Since controller is defined as a name how to accomplish resolve part bellow?
To clarify more in details I want to load some data from server before route is resolved and then use these data in controller.
UPDATE: To be more precise I want each module has its "resolve" function that will be called before root with that controller is executed. Solution in this post (answered by Misko Hevery) does exactly what I want but I don't have controllers as functions but as a names.
The controller definition and resolve parts are to be specified separately on the route definition.
If you define controllers on a module level you need to reference them as string, so:
$routeProvider.when('/someroute', {
templateUrl: 'partials/someroute.html',
controller: 'myController',
resolve: {
myVar: function(){
//code to be executed before route change goes here
};
});
The above code also shows how to define a set of variables that will be resolved before route changes. When resolved those variables can be injected to a controller so taking the example from the snippet above you would write your controller like so:
.controller('myController', ['$scope', 'myVar', function($scope, myVar) {
// myVar is already resolved and injected here
}
]);
This video might help as well: http://www.youtube.com/watch?v=P6KITGRQujQ
#pkozlowski.opensource 's answer works, but I don't really want to mess up my routing and and controllers, because I always keep it separated (from Yo Generator). Actually, we can also have controller and resolve(r) all as string/name (NOT function).
angular.module('mymodule', [
])
.controller('myController', [
'$scope', 'myModelCombination'
function($scope, myModelCombination) {
// myModelCombination[0] === (resolved) myModel
// myModelCombination[1] === (resolved) myModel2
}
])
.controller('myController2', [
'$scope', 'myModel'
function($scope, myModel) {
// Some code here
}
])
.factory('myModel', [
'$scope',
function($scope) {
// return a promise
}
])
.factory('myModel2', [
'$scope',
function($scope) {
// return a promise
}
])
.factory('myModelCombination', [
'$scope', 'myModel', 'myModel2'
function($scope) {
return $q.all(['myModel', 'myModel2']);
}
]);
Then in your routing file this should be added
$routeProvider.when('/someroute', {
templateUrl: 'partials/someroute.html',
resolve: ['myModel'] //ALWAYS IN ARRAY)
});
$routeProvider.when('/myModelCombination', {
templateUrl: 'partials/someroute2.html',
resolve: ['myModel'] //ALWAYS IN ARRAY)
});
http://docs.angularjs.org/api/ng.$routeProvider
This would work too
var MyController = myApp.controller('MyController', ['$scope', 'myData', function($scope, myData) {
// Some code here
}]);
MyController.resolve = {
myData: ['$http', '$q', function($http, $q) {
var defer = $q.defer();
$http.get('/foo/bar')
.success(function(data) {
defer.resolve(data);
})
.error(function(error, status) {
defer.reject(error);
});
return defer.promise;
}]
};
#TruongSinh answer worked for me and is way nicer than having additional functions in the router. I tweaked it a little as it was returning the deferred object instead of the actual resolved data.
$routeProvider.when('/someroute', {
templateUrl: 'partials/someroute.html',
controller: 'SomeController',
resolve: {
myModel: 'myModel'
}
});

Resources