My controller is getting somewhat busy and finding the function that I'm looking for is becoming cumbersome. I'd like to have individual files for some of my controller functions. How can I achieve this? Is there something like ng-include for the controller to use?
You might use the mixin pattern. This allows you to extend your controllers with other controllers. As a result you have now two different controllers, while both get executed at the same time:
app.controller('AnyController', ['$scope'
function ($scope) {
return {
myFunction: function() {
// do something
}
}
}
]);
app.controller('MyMainController', ['$scope'
function ($scope) {
var anyThing = $controller('AnyController as anyThing',{$scope: $scope}),
$scope.anyThing = function() {
// those two options are now both valid:
anyThing.myFunction();
$scope.anyThing.myFunction();
}
}
]);
Now you are able to move your seperate controllers into different files.
Related
I have a directive which is associated with one controller and the functions in my controller defined as
MyFormController.prototype.addNewRow = function addNewRow() {
//Adding row code
};
I want to call this method from another controller, possible ways?
I ve user the service and moved the code into that service which is shared across the controllers, however the service code does the DOM manipulation, and then i guess the next question would be that can we use $compile in a service test case
service or factory is used to share data between controller.so it would be best to define function in service and factory.
demo:
(function() {
angular.module('app', [])
.service('svc', function() {
var svc = {};
svc.method = function() {
alert(1);
}
return svc;
})
.controller('ctrl', [
'$scope', 'svc', function($scope, svc) {
svc.method();
}
]);
})();
You should not!!!
That defeats the whole purpose of modularity.
If possible try to make the function generic and create a service/factory. Now both the places where you need, use the same generic function defined in service and do their stuff.
Otherwise you can also look at events to make changes accordingly.
Look at this blog post:
http://ilikekillnerds.com/2014/11/angularjs-call-controller-another-controller/
Last but the worst solution is (avoid using this, this is literally an aweful way) is catching the element inside directive and getting its scope and taking the function from it.
Example,
var otherControllerFunc = $(".inside-directive").scope().yourfunc;
I have controller (say BaseCtrl) that has a number of functions attached to it. I want to extend BaseCtrl to other controllers that shares some of its functions, however, I only need a function or two (and not all of BaseCtrl's functions). I already saw some posts that demonstrates how to extend a controller, but I wonder if it's possible to extend specific functions only and how to do it?
Extending my comment:
app.controller('parentCtrl', function($scope,$rootscope) {
$rootscope.myPerent = function () {
//your code
}
});
app.controller('childCtrl', function($scope,$rootscope) {
$scope.ourPerent = function () {
$rootscope.myPerent();
}
});
Is it possible to inject a complete module into a controller instead of injecting separately each services?
For example:
var app = angular.module('myApp', ['myApp.core']);
angular.module('myApp.core', [])
.factory('ABService', function() {
return {
getA: function() {
return 'A';
},
getB: function() {
return 'B';
}
}
})
.factory('AnotherService', function() {
return {
calc: function(a, b) {
return a + b;
}
}
})
app.controller('MainCtrl', function($scope, 'myApp.core') {
ABService.getA();
AnotherService.calc(2, 2);
});
Instead of
app.controller('MainCtrl', function($scope, ABService, AnotherService) {
ABService.getA();
AnotherService.calc(2, 2);
});
No.
Why?
You can't inject module to a controller, lets look at this image:
What we can see from this: is that a module is a sort of component it self, which is built on top of controllers, directives, services and filters, and so on.
The real questions coming out of this:
Can a module be without a controller?
Yes.
The is no necessity for a controller in a module. it pretty much depends on the job of that module, it could totally be made out of services and directives.
Can we inject a service from a module to another module's controller?
Yes.
You totally can, this practice is usually being used when you are trying to build a Store site but could happen in much more cases.
You would probably have the module that contains: browsing the items, searching through items, and so on.
But how would you create the cart in that manner?
Let's see: the cart looks like a component to me.
Why?
Because it is something that I would want to test separately from the rest of the code,
It's also built like a component that should have it's own unique services, and directives, and from my point of view should be derived from the rest of the application.
So we should build a module!
Exactly, and whenever you are trying to USE the cart from the store's module's controller, you could simply inject the service that helped you build the cart from that module, and you could apply rules to the store's controller.
In terms of your question:
What I think you are trying to do, or atleast what is possible to do in your situation:
To inject a service from module a into a controller located in module b, there is no need to "inject" the full module into the controller, it doesn't quite make sense.
I hope I explained it as good as it sounds in my head :).
No, but you could wrap your services into one "God" service if you really wanted to (I personally wouldn't recommend it)
angular.module('myApp.core', [])
.factory('ABService', function() {
return {
getA: function() {
return 'A';
},
getB: function() {
return 'B';
}
}
})
.factory('AnotherService', function() {
return {
calc: function(a, b) {
return a + b;
}
}
})
.factory('GodService', function(ABService, AnotherService) {
return {
ABService: ABService,
AnotherService: AnotherService
}
})
Then you could inject the GodService and call ABService and AnotherService off of it.
I'm building a pretty simple app where I have a GlobalController (on body element), and will have another sub-controller below. This is a templated site with multiple, physical pages such that the sub-controller will be different, but at most there will only be a top-level Global one and a single sub-one.
I'm trying to make global functions that any sub-controller can use to run code that each needs to run without having to duplicate the functionality in each sub-controller.
One way I could do this would be to include $rootScope and then emit() messages to the GlobalController who is listening for them using $on().
I gather this is not a "good" way to do this. Rather, I've learned that it's better to use a service for this. I'm now stuck on how to implement this service.
I currently have a Global Controller like so:
var globalModule = angular.module('DoSquareStuff', ["ngRoute","list", "savings-video"]);
// there will be a long list of modules that will be added after "savings-video"
globalModule.factory('squareMgr', function() {
var squares = SUYS.squares; // global obj with earned[] and placed[]
return {
getSquaresEarned: function() {
return squares.earned;
},
getSquaresPlaced: function() {
return squares.placed;
},
setThisSquareEarned: function(value) {
squares.earned.push(value);
},
setThisSquarePlaced: function(value) {
squares.placed.push(value);
},
earnedThisSquare: function(squareNum) {
return ~squares.earned.indexOf(squareNum);
},
placedThisSquare: function(squareNum) {
return ~squares.placed.indexOf(squareNum);
}
}
});
globalModule.controller('GlobalController', function($scope, $squareMgr){
// this would be easy... but it doesn't work
// $rootScope.$on('signal.missionComplete', function (event, missionId) {
// console.log("parentScope receive notice that mission " + missionId + " is complete.");
// });
log('GlobalController loaded');
// log($squareMgr.getSquaresEarned()); //broken
});
Then, reading the docs, I tried:
globalModule.controller('GlobalController', ['squareMgr', function($squareMgr){
// but then how do I get $scope in there?
log('GlobalController loaded');
// log($squareMgr.getSquaresEarned());
}]);
In your last code block, you need to inject $scope as well. You can inject any number of services that you need:
globalModule.controller('GlobalController', ['squareMgr', '$scope',
function($squareMgr, scope){
// but then how do I get $scope in there?
log('GlobalController loaded');
// log($squareMgr.getSquaresEarned());
}]);
And a minor point, I wouldn't put a $ in front of squareMgr, the $ implies it is a built in angular service.
Try
globalModule.controller('GlobalController', ['squareMgr', '$scope', function($scope, squareMgr){ .....
The $ sign is used to differentiate between Angular services and your own
I am working on an angularJS app and I am trying to stick with the most efficient and widely accepted styles of development in AngularJs.
Currently, I am using this way of declaring my services like so:
app.factory('MyService', function() {
/* ... */
function doSomething(){
console.log('I just did something');
}
function iAmNotVisible(){
console.log('I am not accessible from the outside');
}
/* ... */
return{
doSomething: doSomething
};
});
However, there are numerous examples out there and I am not quite sure which design style to follow. Can someone with extensive knowledge about services explain the reason why a certain style is more relevant than another?
Is what I am doing useful in any way other than restricting the access to certain functions in my service?
I would suggest you layout your factory or service as they do in the angular-seed app, except that app annoyingly only uses value in the services.js boilerplate. However you can adapt the layout they use for controllers, directives and filters.
'use strict';
/* Filters */
angular.module('myApp.filters', []).
filter('interpolate', ['version', function(version) {
return function(text) {
return String(text).replace(/\%VERSION\%/mg, version);
}
}]);
Which means for a service you would do:
'use strict';
/* Services */
angular.module('myApp.filters', []).
service('myservice', ['provider1', 'provider2', function(provider1, provider2) {
this.foo = function() {
return 'foo';
};
}]).
factory('myfactoryprovider', ['myservice', function(myservice) {
return "whatever";
}]);
This has more boilerplate than you absolutely need, but it is minification safe and keeps your namespaces clean.
Than all you have to do is decide which of const, value, factory or service is most appropriate. Use service if you want to create a single object: it gets called as a constructor so you just assign any methods to this and everything will share the same object. Use factory if you want full control over whether or not an object is created though it is still only called once. Use value to return a simple value, use const for values you can use within config.
I don't believe there's an accepted standard but I myself follow this convention:
var myServiceFn = function (rootScope, http) { ... };
...
app.factory('MyService', ['$rootScope', '$http', myServiceFn]);
I feel like this is cleaner than defining the function inline and also allows for proper injection if I ever decide to minify my files. (see http://docs.angularjs.org/tutorial/step_05).
As an example, I've been defining services within modules like so:
angular.module('userModule', [])
.service('userService', function() {
this.user = null;
this.getUser = function() {
return this.user;
};
this.userIsNull = function() {
return (this.user === null);
};
this.signout = function() {
this.user = null;
};
})
I think it is more clear to use the .service rather than the .factory?