Route controller resolve mixed up - angularjs

I've a problem with 2 resolves, one for each controller.
http://jsfiddle.net/pvivera/RhAHy/
var app = angular.module('testApp', [], function($routeProvider){
$routeProvider.when('/', {
template: 'Home {{model}}',
controller: 'HomeCtrl',
resolve: HomeCtrl.resolve
})
.when('/About', {
template: 'About {{model}}',
controller: 'AboutCtrl',
resolve: AboutCtrl.resolve
});
});
var HomeCtrl = app.controller('HomeCtrl', function($scope, HomeCtrlData){
$scope.model = HomeCtrlData;
});
HomeCtrl.resolve = {
HomeCtrlData: function($q, $timeout){
var deferred = $q.defer();
$timeout(function(){
return deferred.resolve('AboutCtrlResolver');
}, 2000);
return deferred.promise;
}
};
var AboutCtrl = app.controller('AboutCtrl', function($scope, AboutCtrlData){
$scope.model = AboutCtrlData;
});
AboutCtrl.resolve = {
AboutCtrlData: function($q, $timeout){
var deferred = $q.defer();
$timeout(function(){
return deferred.resolve('AboutCtrlResolver');
}, 2000);
return deferred.promise;
}
};
In the jsfiddler script, when the HomeCtrl want to resolve HomeCtrlData I receive this error Unknown provider: HomeCtrlDataProvider <- HomeCtrlData
If I change HomeCtrlData to AboutCtrlData in the HomeCtrl everything works, it seems that the only resolve that is assigned is AboutCtrl.resolve
Any idea?

The problem here is that app.controller() doesn't return the controller, it returns your application module. So you're assigning app.resolve twice, which is why it doesn't work for one of them.
I would suggest that you inline the resolve function like this instead:
var app = angular.module('testApp', [], function($routeProvider){
$routeProvider.when('/', {
template: 'Home {{model}}',
controller: 'HomeCtrl',
resolve: {
HomeCtrlData: function($q, $timeout) {
var deferred = $q.defer();
$timeout(function(){
return deferred.resolve('HomeCtrlData');
}, 2000);
return deferred.promise;
}
}
})
.when('/About', {
template: 'About {{model}}',
controller: 'AboutCtrl',
resolve: {
AboutCtrlData: function($q, $timeout) {
var deferred = $q.defer();
$timeout(function(){
return deferred.resolve('AboutCtrlData');
}, 2000);
return deferred.promise;
}
}
});
});

Related

AngularJS: Angular UI Bootstrap, pass data from modal to controller

I have correctly setup my angular modal, now I want to pass my modal data back to my controller. I am using the below code.
First my controller calls my factory service that creates the modal popup:
$scope.mymodal = myService.openModal(data);
My service is as:
function openModal (data) {
var uData = null;
if (data) {
uData = {
userName : data.setName,
gender : data.gender
}
}
var modalInstance = $modal.open({
templateUrl: 'modal.html',
controller: 'ModalController',
backdrop: 'static',
keyboard: false,
resolve: {
data: function () {
return uData;
}
}
});
modalInstance.result.then(function () {
return;
}, function () {
});
return modalInstance;
}
See my jsfiddle here for this: http://jsfiddle.net/aman1981/z20yvbfx/17/
I want to pass name & gender that i select on my modal back to my controller, which then populates my page. Let me know what is missing here.
I updated AboutController, ModalController and myService with comments.
Main idea is return data from ModalController with close method. Fiddle
var app = angular.module('myApp', ['ui.router','ui.bootstrap']);
app.controller('IndexController', function($scope, $log) {
});
app.controller("AboutController", ['$location', '$state', '$scope', '$filter','myService', function($location, $state, $scope, $filter, myService) {
var data = "";
$scope.mymodal = myService.openModal(data);
// after modal is close, then this promise is resolve
$scope.mymodal.then(function(resp){
console.log(resp);
})
}]);
app.controller("ModalController", function($location, $state, $scope, $filter, $modalInstance) {
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
$state.go('index');
};
$scope.done = function () {
// return data on close modal instance
$modalInstance.close({genger:$scope.gender,userName:$scope.userName});
};
});
app.factory('ApiFactory', function ($http) {
var factory = {};
return factory;
});
app.factory("myService",[ "$state", "$modal", "ApiFactory",
function ($state, $modal, factory) {
var service = {
openModal: openModal
};
function openModal (data) {
var uData = null;
if (data) {
uData = {
userName : data.setName,
gender : data.gender
}
}
var modalInstance = $modal.open({
templateUrl: 'modal.html',
controller: 'ModalController',
backdrop: 'static',
keyboard: false,
resolve: {
data: function () {
return uData;
}
}
});
// on close, return resp from modal
modalInstance.result.then(function (resp) {
return resp;
}, function () {
});
// return modal instance promise
return modalInstance.result;
}
return service;
}
]);
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/index');
$stateProvider
.state('index', {
url: '^/index',
templateUrl: 'index.html',
controller: "IndexController"
})
.state('about', {
url: '^/about',
templateUrl: 'about.html',
controller: "AboutController"
})
}]);

AngularJS: Error on Factory and routeProvider

In "routeProvider" I have the "objectStats" on resolve, but my controller does not seem to understand it. (I found several problems like on stackoverflow, but no solution solved my error)
My code:
var app = angular.module('AppLearning', ['ngRoute','easypiechart']);
app.config(['$routeProvider',function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'index.html',
controller: 'AppCtrl',
resolve: {
objectStats: function(statsFactory) {
return statsFactory.getStatsFollow();
}
}
}).
otherwise({
redirectTo: '/home'
});
}]);
app.controller('AppCtrl', ['$scope', '$http', 'objectStats', function ($scope, $http, objectStats) {
$scope.statsUnfollow = objectStats.data;
$scope.percent = 65;
$scope.pieOptions = {
animate:{
duration:2000,
enabled:true
},
trackColor: '#e5e5e5',
barColor: '#3da0ea',
scaleColor:false,
lineWidth:5,
lineCap:'square'
};
}]);
app.factory('statsFactory', ['$http', function($http) {
return {
//Code edited to create a function as when you require service it returns object
//by default so you can't return function directly. That's what understand...
getStatsFollow: function (type) {
var q = $q.defer();
$http.get('/api/stats/follow').success(function (data) {
q.resolve(function() {
var settings = jQuery.parseJSON(data);
return settings[type];
});
});
return q.promise;
}
}
}]);
Error: [$injector:unpr] Unknown provider: objectStatsProvider <- objectStats
http://errors.angularjs.org/1.2.9/$injector/unpr?p0=objectStatsProvider%20%3C-%20objectStats
minErr/<#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:78:12
createInjector/providerCache.$injector<#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:3546:19
getService#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:3673:39
createInjector/instanceCache.$injector<#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:3551:28
getService#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:3673:39
invoke#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:3700:1
instantiate#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:3721:23
$ControllerProvider/this.$gethttps://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:6772:18
nodeLinkFn/<#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:6185:34
forEach#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:310:11
nodeLinkFn#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:6172:11
compositeLinkFn#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:5636:15
compositeLinkFn#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:5639:13
compositeLinkFn#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:5639:13
publicLinkFn#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:5541:30
bootstrap/doBootstrap/https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:1304:11
$RootScopeProvider/this.$gethttps://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:11955:16
$RootScopeProvider/this.$gethttps://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:12055:18
bootstrap/doBootstrap/<#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:1302:9
invoke#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:3710:14
bootstrap/doBootstrap#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:1300:1
bootstrap#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:1314:1
angularInit#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:1263:5
#https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js:20555:5
b.Callbacks/c#https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js:3:7852
b.Callbacks/p.fireWith#https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js:3:8658
.ready#https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js:3:3264
H#https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js:3:693

Why can't i use the $http service in a route resolve?

I want to make my views show only after the initial data is fetched and i am trying to accomplish this with a route resolve, but i can't get it to work. What am i doing wrong? Also my angular skills are a bit shabby so i aplogize in advance if my question is dumb.
Application.js :
var Application = angular.module('ReporterApplication', ['ngRoute']);
Application.config(['$routeProvider', '$interpolateProvider',
function($routeProvider, $interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
$routeProvider
.when('/packing/scan.html', {
templateUrl: 'packing/scan.html',
controller: 'PackingScanController',
resolve: {
initData : Application.PackingScanInit()
}
})
.when('/packing/stats.html', {
templateUrl: 'packing/stats.html',
controller: 'PackingStatisticsController'
})
etc
and here is my Scan.js file :
Application.PackingScanInit = function ($q,$timeout,$http) {
var serverData = "";
$http.get('/packing/scan.action')
.success(function(data){
serverData = data;
})
.error(function(data){
serverData = data;
});
return serverData;
}
Application.controller('PackingScanController', ['initData', '$scope', '$http', function(initData, $scope, $http) {
var packer = this;
// Message log model
packer.messageLog = [{
status : "",
message : null
}];
the files are included in this order.
service are singletons means there are initialized only one but time but if you simply return from service it will be called one time but if you return a function from service it will be called again and again .See Below Sample for working.
var app = angular.module('ajay.singhApp', [])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/view1', {
templateUrl: 'views/main.html',
controller: 'MainCtrl',
resolve: {
myVar: function (repoService) {
return repoService.getItems().then(function (response) {
return response.data;
});
}
}
})
.when('/view2', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.otherwise({
redirectTo: '/view1'
});
}]);
app.factory('repoService', function ($http) {
return {
getItems: function () {
return $http.get('TextFile.txt');
}
};
});
Try this:
Application.PackingScanInit = function ($q,$timeout,$http) {
return $http.get('/packing/scan.action')
.success(function(data){
return data;
})
.error(function(data){
return data;
});
}
Also you have to adjust your resolve to this:
resolve: {
initData : Application.PackingScanInit
}
Here is a specific working example:
(function() {
angular.module('app',['ngRoute']);
function TestCtrl($scope, initData) {
$scope.value = initData;
}
angular.module('app').config(function($routeProvider) {
$routeProvider.otherwise({
template: '`<p>Dude {{value}}</p>`',
controller: TestCtrl,
resolve: {
initData: function($http) {
return $http.get('test.json') //change to test-e.json to test error case
.then(function(resp) {
return resp.data.value; //success response
}, function() {
return 'Not Found'; // error response
});
}
}
});
});
})();
http://plnkr.co/edit/SPR3jLshcpafrALr4qZN?p=preview

Angularjs route resolve not populating model before loading controller

I am trying to populate my model from backend(with label and messages) before my contoller get loads. My method is working fine it connects with backend and gets the data but when I am viewing that variable in controller it is coming as undefined. My variable is "Model"
This is my route file
mainApp
.config(["$routeProvider", function ($routeProvider) {
.when(AngularRoutesFactory.AIMSAdmin.SearchBookings, {
templateUrl: aimsAdminViewBase + "Bookings/SearchBookings.html",
controller: "SearchPerioperativeBookingController",
resolve: {
"Model": function (BookingFactory) {
return BookingFactory.GetSearchModel();
}
},
requireAIMSAuthorizeUser: true
})
.otherwise({
redirectTo: AngularRoutesFactory.MainApp.BaseUrl
});
}]);
My Factory is
mainApp.factory("BookingFactory", ["$location", "MainFactory",
function ($location, MainFactory) {
bookingsFactory.GetSearchModel = function () {
bookingsFactory.MainFactory.QueryAPI(apiEndpoint + "GetSearchModel", "GET", function (response) {
bookingsFactory.SearchBookingCriteria = response;
return bookingsFactory.SearchBookingCriteria;
}, null, null, bookingsFactory.LangInfo.Message_GettingBookingModel);
}
return bookingsFactory;
}]);
And this is my controller
mainApp.controller("SearchBookingController", ["$scope", "BookingFactory", "$rootScope", "$location"
, function ($scope, BookingFactory, $rootScope, $location, Model) {
$scope.bbb = Model;
}]);
Edit:
Try handling it this way:
mainApp.config(["$routeProvider", "$q", function ($routeProvider, $q) {
.when(AngularRoutesFactory.AIMSAdmin.SearchBookings, {
templateUrl: aimsAdminViewBase + "Bookings/SearchBookings.html",
controller: "SearchPerioperativeBookingController",
resolve: {
Model: function (BookingFactory, $q) {
var deferred = $q.defer();
BookingFactory.GetSearchModel().then(
function (data) {
deferred.resolve(data);
}, function () {
deferred.reject();
}
);
return deferred.promise;
}
},
requireAIMSAuthorizeUser: true
})
.otherwise({
redirectTo: AngularRoutesFactory.MainApp.BaseUrl
});
}]);
Took guidance from #Fedaykin and came up with following working solution. Please let me know if it is wrong
I just changed my factory method and resolve function by applying $q.defer method and got it working
Changed my factory GetSearchModel method with following code
bookingsFactory.GetSearchModel = function () {
bookingsFactory.MainFactory.QueryAPI(apiEndpoint + "GetSearchModel", "GET", function (response) {
deferred.resolve(response);
}, null, null, bookingsFactory.LangInfo.Message_GettingBookingModel);
return deferred.promise;
}
What I did in route file
var bookingModel= function ($q, BookingFactory) {
var deferred = $q.defer();
BookingFactory.GetSearchModel().then(
function (data) {
deferred.resolve(data);
}, function () {
deferred.reject();
}
);
return deferred.promise;
};
bookingModel.$inject = ["$q", "BookingFactory"];
Then in resolve all I did
.when(AngularRoutesFactory.AIMSAdmin.SearchBookings, {
templateUrl: aimsAdminViewBase + "Bookings/SearchBookings.html",
controller: "SearchBookingController",
resolve: {
"Model": bookingModel
},
requireAIMSAuthorizeUser: true
})
And in controller voila I got the value
mainApp.controller("SearchBookingController", ["$scope", "InitializeMainFactory", "$rootScope", "$location", "Model"
, function ($scope, InitializeMainFactory, $rootScope, $location, Model) {
$scope.Model = Model;
}]);

forwarding in section resolve by RouteProvider to another view

I have a problem with the provider in AngularJS.
I would like to in any view to check whether the user is logged on. If not then it should redirect to / login. On the console, there is no error. I do not know what is wrong.
var app= angular.module("app", ["ngRoute", "ngAnimate", "ngResource"]);
app.config(["$routeProvider", "$locationProvider", function($routeProvider, $locationProvider) {
var getItemNameById = function($route, $location, service, breadcrumbs, path) {
service.getItem($route.current.params.id).then(function(evt) {
if(evt.title) {
$route.routes[path].label = evt.title;
} else if(evt.name) {
$route.routes[path].label = evt.name;
}
breadcrumbs.generateBreadcrumbs();
}, function() {
$location.path("/404");
});
};
$routeProvider
.when("/", {
template: "",
label: "Home",
resolve: function($q, $location) {
alert("in resolve Home...");
var deferred = $q.defer();
if (!isLoggedIn) {
$location.path('/login');
}
deferred.resolve();
return deferred.promise;
}
})
.when("/patient", {
templateUrl: "patient.html",
label: "Patient",
resolve: function($q, $location) {
alert("in resolve Patient...");
var deferred = $q.defer();
if (!isLoggedIn) {
$location.path('/login');
}
deferred.resolve();
return deferred.promise;
}
})
.when("/doctor", {
templateUrl: "doctor.html",
controller: "DoctorController",
label: "Doctor",
resolve: function($q, $location) {
alert("in resolve Home...");
var deferred = $q.defer();
if (!isLoggedIn) {
$location.path('/login');
}
deferred.resolve();
return deferred.promise;
}
});
}]);
app.run(["$rootScope", "LoginService", function($rootScope, LoginService) {
LoginService.checkSession().then(function(response) {
$rootScope.isLoggedIn = response;
}, function(reject) {
$rootScope.isLoggedIn = reject;
});
}]);
why not enter into sections resolve (alert also does not show) on the home page?
best regards
I think you should set a event to route change ,something like this:
app.run(function($rootScope) {
$rootScope.$on("$routeChangeStart", function(event, nextRoute, currentRoute) {
if (nextRoute != null ) {
//Check session
}
});
});

Resources