Resolve not resolved before loading controller - angularjs

I am trying to fetch the value from server side before any controller loads. I am using resolvers to achieve this. Since fetched value needs to be visible to all controllers I extended routeConfig on the following way:
'use strict';
angular.module('myApp', [.....]).
config(['$routeProvider', function ($routeProvider) {
var universalResolves = {
user: function(User, $q, $rootScope) {
var deffered = $q.defer();
User.query({},
function (users) {
deffered.resolve(
$rootScope.activeUser = users[0]
)
}, function(){
deffered.reject();
}
);
return deffered.$promise;
}
};
var customRouteProvider = angular.extend({}, $routeProvider, {
when: function(path, route) {
route.resolve = (route.resolve) ? route.resolve : {};
angular.extend(route.resolve, universalResolves);
$routeProvider.when(path, route);
return this;
}
});
customRouteProvider.when('/users', {
templateUrl: 'partials/users.html',
controller: 'UserController'
});
customRouteProvider.otherwise({redirectTo: '/home'});
}]);
But when I try to print activeUser from the controller I am getting 'undefined'.
.controller('UserController', ['$scope', function ($scope) {
console.log($scope.activeUser.id);
.....
};
Here I am getting the following error:
TypeError: Cannot read property 'id' of undefined.
Why the value is not resolved before loading controller?

There is no such property $promise of deferred object, it is promise:
user: function(User, $q, $rootScope) {
var deffered = $q.defer();
User.query({}, function(users) {
deffered.resolve($rootScope.activeUser = users[0]);
}, function() {
deffered.reject();
});
return deffered.promise;
// ^ don't put $ here
}
Also it's better to inject resolved user to controller then using $rootScope:
.controller('UserController', ['$scope', 'user', function ($scope, activeUser) {
console.log(activeUser.id);
};
An finally just for better codding style, this assignment
$rootScope.activeUser = users[0]
is a little confusing. It's more readable:
$rootScope.activeUser = users[0];
deffered.resolve(users[0]);

Related

I want to share data stored in variable from one controller to another

I have data in one controller and now I want to share it with another but both controller has different modules. I have used $rootscope but it didn't work. I have used service it also didn't work. link here Service
Is there any other way to do. I have spent one week for this please help me.
toolbar.controler
(function ()
{
'use strict';
angular
.module('app.toolbar')
.controller('ToolbarController', ToolbarController);
function ToolbarController($rootScope, $mdSidenav, msNavFoldService, $translate, $mdToast, $location, $localStorage, $http, $scope)
{
var vm = this;
vm.name = $localStorage.name;
vm.userId = $localStorage._id;
vm.readNotifications = function(notifId){
$http({
url: 'http://192.168.2.8:7200/api/readNotification',
method: 'POST',
data: {notificationId: notifId, userId: vm.userId}
}).then(function(res){
vm.rslt = res.data.result1;
console.log(vm.rslt);
vm.refresh();
$location.path('/sharedwishlistdetails');
}, function(error){
alert(error.data);
})
}
}
})();
The data stored here in vm.reslt.
toolbar.module.js
(function ()
{
'use strict';
angular
.module('app.toolbar', [])
.config(config);
/** #ngInject */
function config($stateProvider, $translatePartialLoaderProvider)
{
$translatePartialLoaderProvider.addPart('app/toolbar');
}
})();
Now I want that result for this controller.
sharedwishlistdetails.controller.js
(function ()
{
'use strict';
angular
.module('app.sharedwishlistdetails')
.controller('SharedWishlistDetailsController', SharedWishlistDetailsController);
/** #ngInject */
//NotificationsController.$inject = ['$http', '$location'];
function SharedWishlistDetailsController($http, $location, $localStorage, $rootScope, $scope)
{
var vm = this;
vm.uid = $localStorage._id;
}
})();
shareddata.service.js
(function ()
{
'use strict';
angular
.module('app.core')
.factory('shareData', shareDataService);
/** #ngInject */
function shareDataService($resource,$http) {
var shareData = {};
return shareData;
}
})();
write a service in 'app.toolbar' module
angular.module('app.toolbar').service('ServiceA', function() {
this.getValue = function() {
return this.myValue;
};
this.setValue = function(newValue) {
this.myValue = newValue;
}
});
In your toolbarController , inject ServiceA and set data -
vm.readNotifications = function(notifId){
$http({
url: 'http://192.168.2.8:7200/api/readNotification',
method: 'POST',
data: {notificationId: notifId, userId: vm.userId}
}).then(function(res){
vm.rslt = res.data.result1;
ServiceA.setValue(vm.rslt);
console.log(vm.rslt);
vm.refresh();
$location.path('/sharedwishlistdetails');
}, function(error){
alert(error.data);
})
}
Now write another service for 'app.sharedwishlistdetails' module -
angular.module('app.sharedwishlistdetails',['app.toolbar']).service('ServiceB', function(ServiceA) {
this.getValue = function() {
return ServiceA.getValue();
};
this.setValue = function() {
ServiceA.setValue('New value');
}
});
Now inject ServiceB in your SharedWishlistDetailsController controller and access data -
var sharedData = ServiceB.getValue();
How could $rootScope failed in your code it would be appreciated if you paste your code: never mind here is an example that will help you out:
All applications have a $rootScope which is the scope created on the HTML element that contains the ng-app directive.
The rootScope is available in the entire application.If a variable has the same name in both the current scope and in the rootScope, the application use the one in the current scope.
angular.module('myApp', [])
.run(function($rootScope) {
$rootScope.test = new Date();
})
.controller('myCtrl', function($scope, $rootScope) {
$scope.change = function() {
$scope.test = new Date();
};
$scope.getOrig = function() {
return $rootScope.test;
};
})
.controller('myCtrl2', function($scope, $rootScope) {
$scope.change = function() {
$scope.test = new Date();
};
$scope.changeRs = function() {
$rootScope.test = new Date();
};
$scope.getOrig = function() {
return $rootScope.test;
};
});

Unit test controller

I make an ionic app and it finish but when i start to add tests to it I face a problem with $resources ,in this case I have this Controller :
.controller('newAccountCtrl', function($scope, $window, $rootScope, API, $ionicPopup, $state) {
$scope.newData = {};
$scope.$on('$ionicView.enter', function() {
$scope.newData = {};
});
$scope.newInfo = function() {
API.newAccountInfo().update({ restCode: $scope.newData.restore_code }, $scope.newData, function(res, header) {
$rootScope.popup('success', "OKAY");
$window.location.href = '#/login';
}, function(err) {
if (err.data == null)
$rootScope.popup("Error", "no connection");
else
$rootScope.popup('error', err.data.error);
});
}
})
and in the service i make a request using $resources in function :
angular.module('starter.services', [])
.factory('API', function($rootScope, $resource, $ionicPopup, $ionicLoading, $window) { return {
newAccountInfo: function() {
return $resource(base + '/restoreinfo/:restCode', { restCode: '#_restCode' }, {
update: {
method: 'PUT'
}
}, {
stripTrailingSlashes: false
});
}}});
and in the my test the following code:
describe('newAccountCtrl', function() {
var controller,
deferredLogup, scope, $q;
beforeEach(angular.mock.module('starter'));
// TODO: Load the App Module
beforeEach(module('starter.controllers'));
beforeEach(module('starter.services'));
// TODO: Instantiate the Controller and Mocks
beforeEach(inject(function($controller, _$q_, $rootScope, _API_) {
$q = _$q_;
scope = $rootScope.$new();
API = _API_;
spyOn(API, 'newAccountInfo').and.callThrough(function(callback) {
deferredLogup.promise.then(callback);
return { $promise: deferredLogup.promise };
});
controller = $controller('newAccountCtrl', {
'$scope': scope,
API: API
});
}));
it('#newAccountInfo', function() {
scope.newInfo();
expect(API.newAccountInfo.update).toHaveBeenCalled();
}) });
but I get the error :
Expected a spy, but got undefined.
What I misunderstand here, the code work perfect
just macke factory return the resources direct and remove the functions .

How can I passing Parameter angularjs factory $http and $stateParameters

App.factory('menuService', function ($http) {
var urlBase = 'Services/MenuService.asmx/GetAllMenu';
var factory = {};
factory.getAllMenus= function () {
return $http.get(urlBase);
};
return factory;
});
Controller:
App.controller("sampleController", function ($scope, menuService) {
$scope.List = [];
var menuData=function(data, status){
$scope.List = data;
console.log($scope.List);
}
menuService.getAllMenus().success(menuData);
});
/// Working perfect...
How can i use same service by other controller?
I've tried this one but wrong...
App.controller("viewDetailMenu", function ($scope, menuService, $stateParams) {
$scope.menu = menuService.getMenu($stateParams.id);
});
Here I share image how it look..
Please help me!...
You need to have all functions/methods defined if you want to use them. You getMenu function/method is not defined so it will generate an error. Please look at below code. You can add number of functions. You factory is share by all controllers so you can use it in any controller.
App.factory('menuService', function ($http) {
var urlBase = 'Services/MenuService.asmx/GetAllMenu';
var factory = {};
factory.getAllMenus= function () {
return $http.get(urlBase);
},
factory.getMenu=function(id){
return $http.get(urlBase +"/ID="+ id) // write it according to your API.
}
return factory;
});
And then,
App.controller("viewDetailMenu", function ($scope, menuService, $stateParams) {
$scope.menu = menuService.getMenu($stateParams.id).success(function(data,status){
}).error(function(data,status){
});
});

Provider mock error: Expected a spy, but got Function

I'm very new to jasmine and I got some issue trying to mock a provider.
I have a provider that looks like :
angular.module('myApp')
.factory('MyService', function ($resource) {
return {
actionResource : function(projectId, actionId){
var url = 'blablabla';
if(actionId){
url += "/"+actionId;
}
return $resource(url, {}, {
'create': {
method: 'POST'
}
});
},
};
});
I have a controller using this factory
angular.module('myApp')
.controller('myCtrl', function ($scope, MyService, $state) {
$scope.addAction = function(){
MyService.actionResource($scope.projectId).create($scope.action,
function(){
$state.go('somewhere', {});
});
};
});
and I'd really like to test this controller, at the moment I'm doing something like :
'use strict';
describe('[test] [controller] - myCtrl', function() {
beforeEach(angular.mock.module('myApp'));
//mock creation
beforeEach(
module(function($provide) {
$provide.factory('MyService', function() {
var actionResource = function(projectId, actionId){
var create = function(){return {}};
return {create:create};
}
return {actionResource:actionResource}
}
)})
);
var $httpBackend, $rootScope, myController, mockMyService;
var scope = {};
beforeEach(angular.mock.inject(function($injector, $rootScope, MyService) {
var $controller = $injector.get('$controller');
scope=$rootScope.$new();
mockMyService = MyService;
spyOn(mockPilotageService, 'actionResource').and.callThrough();
spyOn(mockPilotageService.actionResource(), 'create');
createController = function() {
return $controller("myCtrl", {$scope:scope, myService:mockMyService});
};
}));
it('myCtrl - addAction() calls actionRessource.create() method', function() {
createController();
scope.addAction();
expect(mockMyService).toBeDefined();
expect(mockMyService.actionResource).toHaveBeenCalled();
expect(mockMyService.actionResource().create).toHaveBeenCalled();
});
});
and I'm getting this error :
Error: Expected a spy, but got Function.
at /Users/*****/myController.spec.js:86
So it's able to spy on mockMyService.actionResource but not on mockMyService.actionResource().create. I can't understand why
any help would be more than welcome
thanks

Load views after services in angularjs

In my angular app I have a view, a controller and a service.
The service load resources ex:service load persons and initialize value with the result.
I want to load my view after my service finish his function to load his resources.
var myApp = angular.module('myApp',[]);
myApp.controller('PersonsCtrl', ($scope, Persons) {
$scope.persons = Persons.data;
});
myApp.factory('Persons', {
data: [[function that load resources => take time]]
});
So I want to load my controller when my service finish his initialization.
Some ideas?
Assuming you have a route provider, here's a basic example. When the promise is resolved, "personData" will be injected into your controller. There's not much info about what your service does, so I had to give something very generic.
myApp.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/persons', {
controller: 'PersonsCtrl',
templateUrl: 'persons.html',
resolve: {
personData: ['Persons', function(Persons) {
return Persons.getData();
}]
}
});
}]);
myApp.controller('PersonsCtrl', ($scope, personData) {
$scope.persons = personData;
});
myApp.factory('Persons', {
getData: function() {//function that returns a promise (like from $http or $q)};
});
Maybe try using promises, example below
var myApp = angular.module('myApp',[]);
myApp.controller('PersonsCtrl', ($scope, Persons) {
$scope.persons = Persons.getData().then(function(response){
//do whatever you want with response
});
});
myApp.factory('Persons', function ($http, $q) {
return {
getData: function () {
var def = $q.defer();
$http.get('url').
success(function (response) {
def.resolve(response);
})
return def.promise();
}
}
});

Resources