Grouping Angular services together to inject them in multiple Controllers - angularjs

I am currently trying to refactor everything on our company following best practices and JohnPapa's style guide, which means that among other things, I am supposed to switch from setTimeout to $timeout, setInterval to $interval, etc.
However, I find it tiring, messy, and counter-intuitive to have to inject those services every single time. This results in long repetitive controller declarations where half of the elements are useless and obvious.
angular.module('myModule',[])
.controller('MyController', ['$scope', '$http', '$timeout', '$interval', MyController])
.controller('MyController2', ['$scope', '$http', '$timeout', '$interval', MyController2])
.controller('MyController3', ['$scope', '$http', '$timeout', '$interval', MyController3])
I find this ugly, and a pain to maintain; this is the reason why I've always favored setTimeout over $timeout, but now I'm trying to improve.
Would there be a way to "mass inject" services?
For example something such as:
var baseServices = {
http: $http,
scope: $scope,
timeout: $timeout,
interval: $interval,
};
angular.module('myModule',[])
.controller('MyController', ['baseServices', MyController])
.controller('MyController2', ['baseServices', MyController2])
.controller('MyController3', ['baseServices', MyController3])
var MyController = function(baseServices){
baseServices.$timeout(...);
}
Is this something remotely possible?

Maybe you could use a factory to group all these services and use it from your controller
angular.module('myModule',[])
.controller('MyController', ['baseServices', MyController])
angularApp.factory('baseServices', baseServices );
function baseServices ($scope, $http, $timeout, $interval) {
return {
scope: $scope,
http: $http,
timeout: $timeout,
interval: $interval
};
}

Related

Can I have two angular.module calls to the same ng-app in two different files for same controller?

Hi I have created two angulerjs files for same ng-app example.
admin.js
var app = angular.module('arcadminmodule', ['ngTable', 'ui-notification']);
app.controller('ArcAdminController', ['$http', '$scope', '$filter', '$interval', 'ngTableParams', 'Notification', function($http, $scope, $filter, $interval, ngTableParams, Notification) {});
admin1.js
var app = angular.module('arcadminmodule');
app.controller('ArcAdminController', ['$http', '$scope', '$filter', '$interval', 'ngTableParams', 'Notification', function($http, $scope, $filter, $interval, ngTableParams, Notification) {});
But its overriding admin.js from admin1.js
please help me out....
In admin1.js when you write:
var app = angular.module('arcadminmodule');
you are not creating a new module. You are trying to get an existing module named 'arcadminmodule'.. If you want to create a new module, you will have to write something like this:
var app = angular.module('arcadminmodule',[]); // add your depencencies...
Now, In your case, in admin.js you are creating your module and admin1,js you are making use of the same module. In angular you cannot have two controllers with the same name. Controllers are for (from the docs):
Set up the initial state of the $scope object.
Add behavior to the $scope object.
So If you need are trying to apply some roles or some business logic, It need to go into one controller. Make sure your controller contain only the business logic needed for a single view.
I think its no need for use the same controller in two places.But you can use services in places.If you need to do some think different from the ArcAdminController,use this structure.
Services
-service1.js
(function (angular) {
angular.module('marineControllers').service('boatService', function (ajaxService) {
}
)
-service2.js
-module..js
var artistControllers = angular.module('marineControllers',['ngAnimate']);
Controllers
-controller1
(function (angular) {
angular.module('marineControllers').controller("BoatController", ['$scope', '$http', '$routeParams',
'dashboardService', '$filter', 'loginService', '$location', 'boatService', 'autocompleteFactory', 'utilityFactory',
function ($scope, $http, $routeParams, dashboardService, $filter, loginService, $location, boatService, autocompleteFactory, utilityFactory) {
function loadAllFishingBoat() {
$scope.boatsTable.length = 0;
if (!$scope.$$phase)
$scope.$apply();
boatService.getAllBoatAndDevice().then(function (data) {
$scope.boatsTable = data;
if (!$scope.$$phase)
$scope.$apply();
});
};
}]);
})(angular);
-controller2
(function (angular) {
angular.module('marineControllers').controller("DeviceController", ['$scope', '$http', '$routeParams',
'dashboardService', '$filter', 'loginService', '$location', 'deviceService', 'autocompleteFactory', 'utilityFactory','commonDataService',
function ($scope, $http, $routeParams, dashboardService, $filter, loginService, $location, deviceService, autocompleteFactory, utilityFactory,commonDataService) {
function loadAllFishingBoat() {
$scope.boatsTable.length = 0;
if (!$scope.$$phase)
$scope.$apply();
boatService.getAllBoatAndDevice().then(function (data) {
$scope.boatsTable = data;
if (!$scope.$$phase)
$scope.$apply();
});
};
}]);
})(angular);
I have been use many services in both controllers,still they are different logics.

AngularJS - is there any dependency injection container?

Have a look into my AngularJS controller:
MyApp.controller('MyAppController', function($scope, $http, $filter,
$location, $window, FileUploader) {
// ...
});
Is there any Dependency Injection Container or current approach looks fine?
It looks fine, but if you plan on minifying your code later on you will need to write the code like this instead so that Angular knows what to inject:
MyApp.controller('MyAppController', ['$scope', '$http', '$filter', '$location', '$window', 'FileUploader', function($scope, $http, $filter, $location, $window, FileUploader) {
...
}]);
If you use Gulp, there is a plugin ng-annotate which I've found very useful and it takes care of this extra code for you. Saves you from having to write everything twice.
Angularjs takes care of the dependency injection for you, but to put the dependencies in an array like below, explicitly states what should be injected. If the parameters in the function are minified to 'a', or 'b', the array let's angularjs know what to inject.
MyApp.controller('MyAppController', ['$scope', '$http', '$filter', '$location', '$window', 'FileUploader', function($scope, $http, $filter, $location, $window, FileUploader) {
...
}])

Angularjs - injecting dependencies into multiple controllers

I'm still quite new to angular, and have been building a simple CRM application. For a single resource (restful API resource) I have 3-4 routes and controllers defined in my angular application. Now, there are a set of services and modules that I repeatedly have to inject into each controller. I understand that each controller will have it's own instance of scope and shared instance of factory/services but is there a way to centrally define dependencies for multiple controllers?
In the example below, $modal, growl, configuration, $scope are injected into all 3 controllers, I'd like to define that only once.
Listings Controller
myApp.controller('VenueListCtrl', ['$scope', '$http', 'configuration', '$modal', 'growl',
function ($scope, $http, configuration, $modal, growl) {
}
]);
Create/New Controller
myApp.controller('VenueCreateCtrl', ['$scope', '$http', '$location', 'configuration',
function ($scope, $http, $location, configuration) {
}
]);
Details Controller
myApp.controller('VenueDetailCtrl', ['$scope', '$routeParams', '$http', '$modal', 'configuration',
function ($scope, $routeParams, $http, $modal, configuration) {
}
]);
Best you can do is: use not-anonymous function declaration of controllers:
var depsToInject = ['$scope', 'growl', 'configuration', '$modal'];
myApp.controller('Ctrl1' , Ctrl1);
Ctrl1.$inject = depsToInject ;
function Ctrl1($scope, growl, configuration, $modal) {
// ...
}
myApp.controller('Ctrl2' , Ctrl2);
Ctrl2.$inject = depsToInject ;
function Ctrl1($scope, growl, configuration, $modal) {
// ...
}
etc. But that does not fully unify declaration and I don't think there is a better way. However you can try from the other side and wrap your dependencies with another dependency, but I don't like this way either.

AngularJS 1.3.0 + TypeScript controller definition issue

In our application we use the "controller as" syntax:
<div class="workspace-header" ng-controller="LoginController as loginCtl">
To define the LoginController, we define it as a TypeScript class:
class LoginController {
// variables here
constructor($rootScope, $http, $location, $cookieStore, AuthService, AUTH_EVENTS, localStorageService) {
// set variables
this.$rootScope.$on(AUTH_EVENTS.logoutSuccess, () => {
this.logout();
});
}
public login(credentials: any): void {
this.AuthService.login(credentials).then(() => {
// login success
}, () => {
// login failed
});
}
public logout() {
}
}
and instantiate it this way:
.controller('LoginController', ['$rootScope', '$http', '$location', '$cookieStore', 'AuthService', 'AUTH_EVENTS', 'localStorageService',
($rootScope, $http, $location, $cookieStore, AuthService, AUTH_EVENTS, localStorageService) =>
new LoginController($rootScope, $http, $location, $cookieStore, AuthService, AUTH_EVENTS, localStorageService);
])
After upgrading to AngularJS 1.3.0 this does not work at all. The "controller as" syntax is completely broken (when used in this fashion). We define a form on the page with ng-submit:
<form name="loginForm" ng-submit="loginCtl.login(dc.credentials)" novalidate>
... fields here
<button type="submit">Login</button>
</form>
The loginCtl.login() does nothing, and no errors are output to the console.
After a lot of debugging and some digging, I believe the breaking change in AngularJS is this:
https://github.com/angular/angular.js/issues/8876
https://github.com/angular/angular.js/pull/8882 (added note to documentation)
If I modify my controller as such:
.controller('LoginController', ['$rootScope', '$http', '$location', '$cookieStore', 'AuthService', 'AUTH_EVENTS', 'localStorageService',
function ($rootScope, $http, $location, $cookieStore, AuthService, AUTH_EVENTS, localStorageService) {
var loginCtrl = new LoginController($rootScope, $http, $location, $cookieStore, AuthService, AUTH_EVENTS, localStorageService);
// since controllers always return 'this', extend 'this' with the controllers
// properties and it's prototype's properties
_.extend(this, loginCtrl);
_.extend(this, loginCtrl["__proto__"]);
}
])
Then I can get it working, but this seems messy (and I'm not sure if I would have to chain up prototypes in case of superclasses).
Has anyone else run into this and have a better approach for defining these classes in TypeScript?
As PSL said, this is the problem:
.controller('LoginController', ['$rootScope', '$http', '$location', '$cookieStore', 'AuthService', 'AUTH_EVENTS', 'localStorageService',
($rootScope, $http, $location, $cookieStore, AuthService, AUTH_EVENTS, localStorageService) =>
new LoginController($rootScope, $http, $location, $cookieStore, AuthService, AUTH_EVENTS, localStorageService);
])
You can simply use LoginController in place of the giant arrow function.
See this comment in the issue you linked about how returning an object is incorrect; the function needs to be something that works when the new operator is used on it.
As PSL said but with $inject... I posed a similar question Angular 1.3 breaking changes - scope set but reset before $apply
I've put my answer here: http://plnkr.co/edit/NMPXFd67WLXHjhrfync2
//other dependencies deleted for brevity
.controller('LoginController', ['$scope', LoginController]);
LoginController.$inject = ['$scope'];

how to pass multiple services in controller in angularjs?

I have a service called authService. I call it from the Logincontroller as follows :
angular.module('myApp').controller('LoginController',function($q, $scope, $location,$routeParams, $window, authService) {//some code here});
this works fine.
Now I have another service called regService which is like :
angular.module('myApp').factory('regService ', function ($window, $q, $rootScope) {//some code here});
Now in LoginController how do I call functions from regService ?
Both existing answers are technically correct, but if you decide to minify/uglify your code anytime in the future, those solutions will eventually break.
To prevent this, John Papas AngularJS style guide favors the use of the $inject service in Y091 like so :
angular.module('myApp').controller('LoginController', LoginCtrl);
LoginCtrl.$inject = ['$q', '$scope', '$location', '$routeParams', '$window', 'authService', 'regService'];
function LoginCtrl($q, $scope, $location, $routeParams, $window, authService, regService) {
//some code here
}
Just do it like authService, you just need to add regService. AngularJS will automatically bind the service based on name. You might want to understand more about Dependency Injection - https://docs.angularjs.org/guide/di
angular.module('myApp').controller('LoginController',function($q, $scope, $location,$routeParams, $window, authService, regService) {//some code here});
Just do:
angular.module('myApp')
.controller('LoginController', function($q, $scope, $location, $routeParams, $window, authService, regService) {
});

Resources