Inject Angular factory into controller - angularjs

I decided to base my AngularJS project on angular-seed if found on GitHub. But I have a problem with factory that I try to call from my controller.
I have controller like this:
(function() {
'use strict';
angular.module('myApp.authentication', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/authentication', {
templateUrl: 'views/authentication/authentication.partial.html',
controller: 'AuthenticationCtrl',
controllerAs: 'vm',
bindToController: true
});
}])
AuthenticationCtrl.$inject = ['authenticationService']
.controller('AuthenticationCtrl', [function(authenticationService) {
var vm = this;
vm.login = function() {
var all = authenticationService.getAll();
console.log("login" + all)
}
}]);
})();
So when vm.login() get triggered I want to call authenticationService.getAll();to get data from my service as below:
(function () {
'use strict';
angular
.module('myApp')
.factory('authenticationService', authenticationService);
function authenticationService() {
var service = {
getAll: getAll
};
return service;
function getAll() {
return [
{first: 'Alan', last: 'Dex', lunchMoney: 123},
{first: 'Ada', last: 'True', lunchMoney: 82},
{first: 'Adam', last: 'Mc Donald', lunchMoney: 122},
{first: 'Anthony', last: 'Heys', lunchMoney: 322},
{first: 'Pamela', last: 'Anders', lunchMoney: 422}
];
}
}
})();
But I got following error Uncaught ReferenceError: AuthenticationCtrl is not defined Is that because I try to inject factory into controller that is not created yet? If so how should I write this piece?

Make the followinf changes to your controller :
(function() {
'use strict';
angular.module('myApp.authentication', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/authentication', {
templateUrl: 'views/authentication/authentication.partial.html',
controller: 'AuthenticationCtrl',
controllerAs: 'vm',
bindToController: true
});
}])
.controller('AuthenticationCtrl', AuthenticationCtrl);
AuthenticationCtrl.$inject = ['authenticationService']
function AuthenticationCtrl(function(authenticationService) {
var vm = this;
vm.login = function() {
var all = authenticationService.getAll();
console.log("login" + all)
}
});
})();
Actually you are trying to inject service to your controller before defining that controller.i.e. when it tries to inject service it don't found the controller.
Thanks & Cheers

If you want to define your controller explicitly as a function, then you need write it like so:
function AuthenticationCtrl (authenticationService) {
var vm = this;
vm.login = function() {
var all = authenticationService.getAll();
console.log("login" + all)
}
};
AuthenticationCtrl.$inject = ['authenticationService'];
angular.module('myApp.authentication')
.controller('AuthenticationCtrl', AuthenticationCtrl);
I suggest to write dependencies in that way:
.controller('AuthenticationCtrl', ['authenticationService', function(authenticationService) {
var vm = this;
vm.login = function() {
var all = authenticationService.getAll();
console.log("login" + all)
}
}]);
Seems more readable and less lines of code

Related

Angular testing stateprovider always returns null

I'm using Karma to write angular tests: Here's my spec.js file:
'use strict';
var state;
var $rootScope, $state, $injector, CategoriesService;
describe('Categories', function() {
describe('Categories Manage', function() {
beforeEach(function() {
beforeEach(module('ui.router'));
module('CL.Categories', function($provide) {
$provide.value('CategoriesService', CategoriesService = {});
});
inject(function(_$rootScope_, _$state_, _$injector_, $templateCache, _CategoriesService_) {
$rootScope = _$rootScope_;
$state = _$state_;
$injector = _$injector_;
CategoriesService = _CategoriesService_;
// We need add the template entry into the templateCache if we ever
// specify a templateUrl
$templateCache.put('layout/dashboard.html', '');
$templateCache.put('layout/sidebar.html', '');
$templateCache.put('layout/footer.html', '');
$templateCache.put('layout/header.html', '');
$templateCache.put('categories/manage/index.html', '');
});
});
it('should respond to URL with query parameters', function() {
expect($state.href(state)).toEqual('#/categories/manage');
});
});
});
This is my config file :
(function (){
'use strict';
angular.module('CL.Categories')
.config(['$stateProvider', categoriesConfig]);
function categoriesConfig ($stateProvider){
$stateProvider
.state('dashboard.selectCategories', {
url: "/categories/select?criteria&referrer&index",
templateUrl: 'categories/select/index.html',
controller: 'SelectCategoriesController',
controllerAs: 'vm',
resolve: {
categoryRoot: ['CategoriesService', function(CategoriesService){
return CategoriesService.getRootCategories();
}]
}
})
.state('dashboard.manageCategories', {
url: "/categories/manage?active",
templateUrl: 'categories/manage/index.html',
controller: 'ManageCategoriesController',
controllerAs: 'vm',
resolve: {
workCategories: ['CategoriesService', function (CategoriesService) {
return CategoriesService.getCategoriesByOrganisationWithCertificates();
}]
}
});
}
})();
in my karma.config file I have the base path set to './'. the test expect($state.href(state)) always returns null
When you're making your mock call for state, try this instead to get the 'state':
state = $state.get('dashboard.selectCategories');
Then you can test pieces of the state declaration:
expect(state.url).toEqual('/categories/select?criteria&referrer&index');
expect(state.templateUrl).toEqual('categories/select/index.html');
And so on...

How to use one controller inside another one

I would like to use one controller inside another one. I have found that I could use angular service $controller.
This is what I have tried:
.controller(
'UnplannedTasksController',
[
'$location',
'$uibModal',
'$controller',
'unplannedTasksService',
'messages',
function($location, $uibModal, $controller, unplannedTasksService, messages) {
var ctrl = this;
var modalInstanceCtrl = $controller('ModalInstanceCtrl');
this.openModal = function(unplannedTask) {
var modalInstance = $uibModal.open({
animation: false,
templateUrl: 'unplanned-tasks/unplanned-tasks-modal.html',
controller: modalInstanceCtrl,
controllerAs: 'mdCtrl',
size: 'lm',
resolve: {
object: function() {
return unplannedTask;
},
title: function() {
return messages.unplannedTasks.deleteTitle;
},
question: function() {
return messages.unplannedTasks.deleteQuestion + unplannedTask.partner.name;
}
}
});
modalInstance.result.then(function(unplannedTask) {
ctrl.display.getUnplannedTasksBusyPromise = unplannedTasksService.removeUnplannedTask(unplannedTask.id).then(function(data) {
ctrl.searchUnplannedTasks();
});
});
};
}])
This ModalInstanceCtrl is in another file and look like this:
.controller('ModalInstanceCtrl', function($modalInstance, object, title, question) {
var ctrl = this;
this.object = object;
this.title = title;
this.question = question;
this.ok = function() {
$modalInstance.close(ctrl.object);
};
this.cancel = function() {
$modalInstance.dismiss('cancel');
};
})
But I am getting an error:
"Error: [$injector:unpr] Unknown provider: $modalInstanceProvider <- $modalInstance <- ModalInstanceCtrl ..."
Could you please advise. Thank you.
[EDIT]
Anyone? Please ...
Best regards,
mismas
According to the Angular-UI documentation, you do not need to use $controller. You just have to tell the controller name the the $uibModal service, as a simple string.
In your case:
var modalInstance = $uibModal.open({
controller: 'modalInstanceCtrl'
// + more params
});

i am trying to test my angular controller using jasmine. But i am getting Error: [$injector:modulerr]

following is the code from my sample angular project.
app.js code:
(function () {
'use strict';
var app = angular.module('actorsDetails', [
// Angular modules
'ngResource',
// 3rd Party Modules
'ui.bootstrap',
'ui.router'
]);
app.config(['$stateProvider', '$urlRouterProvider', configRoutes]);
function configRoutes($stateProvider, $urlRouterProvider) {
$stateProvider
.state('main', {
url: '/main',
templateUrl: 'app/home/home.html',
controller: 'HomeCtrl',
controllerAs: 'vm'
})
.state('form', {
url: '/form',
templateUrl: 'app/form/form.html',
controller: 'FormCtrl',
controllerAs: 'vm',
resolve: {
initialData: ['actorApi', function (actorApi) {
return actorApi.getActorsResource();
}]
}
})
.state('resource', {
url: '/resource',
templateUrl: 'app/resource/resource.html',
controller: 'ResourceCtrl',
controllerAs: 'vm',
resolve: {
initialData: ['actorApi', function (actorApi) {
return actorApi.getActorsResource();
}]
}
});
$urlRouterProvider.otherwise('/main');
}
app.run(['$state', function ($state) {
// Include $route to kick start the router.
}]);
})();
controller code:
(function () {
'use strict';
angular.module('actorsDetails').controller('HomeCtrl', HomeCtrl);
/* #ngInject */
function HomeCtrl($state) {
/* jshint validthis: true */
var vm = this;
vm.activate = activate;
vm.test = true;
vm.navigate = navigate;
activate();
function activate() {
}
function navigate() {
$state.go('form');
}
}
})();
**test.js**
describe('HomeCtrl', function() {
beforeEach(module('actorsDetails'));
beforeEach(inject(function ($rootScope, $controller) {
var scope = $rootScope.$new();
var HomeCtrl = $controller('HomeCtrl', {
$scope: scope
});
}));
it('should have a HomeCtrl controller', function() {
expect(true).toBeDefined();
});
});
there are the files I have included in my karma.config.js
I have added all the angularJS dependent files.
I have also added the controller file that i need to test
files: [
'src/lib/angular/angular.min.js',
'src/lib/angular-mocks/angular-mocks.js',
'src/lib/angular-resource/angular-resource.min.js',
'src/lib/angular-route/angular-route.min.js',
'src/app/app.js',
'src/app/home/home.controller.js',
'src/test/specs/*.js'
],
kindly pinpoint me, what is that I am doing wrong...
Mock out the $state object in your unit test.
var mockState = { go: function() {} };
var HomeCtrl = $controller('HomeCtrl', { $scope: scope, $state: mockState });
The $injector:modulerr is most likely related to your use of $state in your controller. Instead of mocking, you could try adding the library to your karma config, and loading the module in your unit test.
'src/lib/angular-ui-router/release/angular-ui-router.min.js'
beforeEach(module('ui.router'));

Angular Modal Cannot Resolve From Factory

I have an AngularJS factory which I am attempting to use to create modals. However, when I attempt to use the resolve method in the $modal my modal instance controller gets an unresolved provider.
Here is how I am calling my factory from my controller:
var modalOptions = {
template: 'app/common/modalwindow.html',
data: data
};
modalFactory.openModal(modalOptions);
My modal factory is simple for now, all it has is a single open modal method:
(function() {
'use strict';
var factoryId = 'modalFactory';
angular.module('app').factory(factoryId, ['$modal', modalFactory]);
function modalFactory($modal) {
var factory = {
openModal: openModal
}
return factory;
function openModal(data) {
$modal.open({
templateUrl: data.template,
controller: 'modalInstanceCtrl',
resolve: {
modalData: function () {
return data.data;
}
}
});
}
}
})();
However, when my modalInstanceCtrl is called it throws an error. Here is my modalInstanceCtrl
(function () {
'use strict';
var controllerId = 'modalInstanceCtrl';
angular.module('app').controller(controllerId, ['common', 'modalData', modalInstanceCtrl]);
function modalInstanceCtrl(common, modalData) {
var getLogFn = common.logger.getLogFn;
var log = getLogFn(controllerId);
log(modalData);
};
})();
The error it throws is:
Unknown provider: modalDataProvider <- modalData <- modalInstanceCtrl
I thought the resolve in the $modal would handle this injection. Am I assuming wrong here?

Angular trying to pass parameter to a service

Trying to pass a parameter to a service like this
.service('modalService', ['$modal','$log', function ($modal,$log) {
'use strict';
this.showcodeModal = function(testing) {
$log.warn("gets here");
$log.warn(testing);
$modal.open({
templateUrl: 'views/modal/showcode.html',
controller: 'showcodeCtrl',
windowClass: 'code-result',
resolve: {
address: function () {
return 'test variable';
}
}
});
};
}])
But always returns "undefined" for my parameter "testing".
And it's called from my controller like this
var test = "test";
modalService.showcodeModal(test);
The following works fine. Formatted a bit differently, if that helps.
var myApp = angular.module('myApp',[]);
myApp.controller('myCtrl', ['$scope','myService',
function ($scope,myService) {
myService.showcodeModal('testing');
}]);
myApp.service("myService",["$http",
function($http) {
return {
showcodeModal:function(aval) {
console.log(aval);
}
};
}]);

Resources