I am learning Angular and need to create some custom filters.
Do I create one filters.js file and put all my filters in there similar to all my reusable factory.js?
Eg: I have a utilsFactory.js and I put reusable functions in here.
Does this then get injected into the controllers? Or is this loaded in the $rootscope somewhere?
I have seen many examples on how to create them but not how to store and manage them and how to access them properly
filter.js
angular.module('achApp', [])
.filter('myUpperCase', function(){
return function(value){
return String(value).toUpperCase();
}
});
Controller
(function(){
var DevbController = function($scope, utilsFactory, $filter){
$scope.greeting = 'hello';
};
DevbController.$inject = ['$scope', 'utilsFactory', '$filter'];
angular.module('achApp')
.controller('DevbController', DevbController)
}());
Filters are generally created for use in your templates (HTML). For example:
<p>{{somethingOnScope | myFilter}}</p>
You can use them in your JS files by injecting $filter, and then getting a reference to your filter like: $filter('myFilter');
You can see usage examples in the filter documentation:
https://docs.angularjs.org/api/ng/filter/filter
Where and how exactly you register your filters is a matter of style. I personally try to follow john papa's advice and create only one injectable item per file.
On another subjective note, I prefer to minimize the use of filters, especially custom ones. If you want to use them primarily in your JS, a service/factory feels cleaner to me, and if you're tempted to create one for use in your templates, often you can instead just change the thing before putting it on the scope.
Related
I need to make some custom directives. Every tutorial shows building the directive relative to the controller where it is to be used. I'm sure this is not the right way if you need to put it into another controller.
I have a global controller. Should I put my directives there? I also have a Utilities factory and inject this into my controllers(this keeps everything tidy and manageable). Do directives work the same way?
How do you manage multiple directives and where do you put them?
Add your directives in separate file like directives.js and use those directives in many views or controllers.
directive.js should be included after your app.js
For example if your app.js is like:
var app = angular.module('myangularapp', ['ngResource']);
then your directive.js should be like:
app.directive('confirm', function(ConfirmService) {
});
app.directive('alert', function(AlertService) {
});
So with regular jquery, I can do:
var = variable.data('data-attribute');
What would be the correct way to do this with Angular?
There are various ways to do this, you should even use the jQuery command that you wrote above to read data attribute. Do this inside a controller and you are OK. I used jQuery for readability sake, you should use jQueryLite or even Vanilla Javascript.
In your controller:
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.expando = $( "#testId" ).data( "test" );
});
and in your view:
<p id="testId" data-test="this is expando attr">Hello {{name}}, {{expando}}!</p>
See the plunker for example.
This hovewer (maybe) is not the best solution! More suitable should be the use of a directive. Probably that attribute is something that you read inside a Javascript function to do something with the DOM, and the directives are the angular way to reuse component that alter the DOM.
So, your question can't have a better answer until you don't specify what's the use of that data-attribute.
what I am trying to do here is to create a similar controller but not exactly the same, a few aspects of the controller need to be override. if it is the case in java then I probably just subclass and override the method I needed. but here in AngularJs not sure what is the best way to achieve this.
I really don't want to duplicate the code. refactoring the existing code is preferred but due to timeline issue have to delay that a bit.
so what is the correspondence of subclass and override in AngularJS
When you really need controller inheritance (including $scope), I think your question is best answered here: What's the recommended way to extend AngularJS controllers?
You can create a service and inherit its behaviour in any controller just by injecting it.
app.service("reusableCode", function() {
var reusableCode = {};
reusableCode.commonMethod = function() {
alert('Hello, World!');
};
return reusableCode;
});
Then in your controller that you want to extend from the above reusableCode service:
app.controller('MainCtrl', function($scope, reusableCode) {
angular.extend($scope, reusableCode);
// now you can access all the properties of reusableCode in this $scope
$scope.commonMethod()
});
DEMO PLUNKER: http://plnkr.co/edit/EQtj6I0X08xprE8D0n5b?p=preview
I have a collection that I need to access in all of my nested scopes. Inside my directive templates, inside my directives in ng-repeat... n levels deep. I don't want to have to say $scope.$parent.$parent.$parent....$parent.MyList.
I've tried using $rootScope, but clearly I lack the understanding of how this works. I pass it into my directive during the declaration like so:
$rootScope.MyList = ["list": 1];
...
...
MyApp.directive('mydirective', ['$rootScope', function ($rootScope) {
return {
restrict: 'A',
replace: false,
link: function (scope, rootScope) {
}
}
}])
The rootScope does not contain MyList. Is there something I'm doing wrong, or a better way to do it? I've thought of using a Factory or Service, but I don't know how to set that up and we all know how crappy the documentation is for Angular, so searching is very frustrating.
Can you provide a plnkr or jsfiddle reproducing this behavior? I can get the controller to communicate with service using $rootScope.
http://plnkr.co/edit/IEhOde
However, you'd probably want to create a service which would cache the value that you want and inject it in your directive and retrieve the value.
First of all $rootScope.MyList = ["list": 1] has syntax error, should be $rootScope.MyList = ["list", 1] or $rootScope.MyList = [{"list": 1}].
Anything you assign to $rootScope is accessible within child $scopes (except isolate scopes) due to prototype inheritance.
Generally if you want to share something within whole app, you can assign it to $rootScope as you did or you can create top level AppCtrl which will have something like $scope.MyList=... and all nested scopes will have access to it. Second option is bit better when it comes to testability as you can inject service to AppCtrl which provides MyList data. You can see this pattern in action here AngularJS GlobalCtrl vs $rootScope vs Service.
A service/provider is the recommended approach.
For just a list of data you can use the value provider:
app.value('listService', {
MyList : {"list": 1}
});
Inject it where you need it, and you can include it in the relevant scopes as such:
app.controller('Ctrl', function($scope,listService) {
$scope.list = listService.MyList;
});
A fiddle of that: http://jsfiddle.net/qKcQL/
Injecting it where you need is good for documentation and maintenance. But if you really need this on the global $rootScope then this will accomplish that:
app.controller('Ctrl', function($scope,listService,$rootScope) {
$rootScope.list = listService.MyList;
});
$rootScope fiddle: http://jsfiddle.net/qKcQL/1/
In most demos below method is given
First Method:
function MyCtrl( $scope ){
$scope.someValue = "All your base are belong to us!";
}
Second Method:
app.controller("MyController",funciton( $scope ){
$scope.someValue = "All your base are belong to us!";
});
What are the pros and cons of using either method?
I'll try to give a quick summary each options pros and cons.
1) The following version is often used in examples around the web because it's easy to write. I wouldn't recommend it in real code however, for two reasons. First of all it can break horribly if you minify your code (and you should), secondly you are littering with globals which is generally bad form and encourages sloppy dependencies that are hard to test.
function MyCtrl( $scope ){
$scope.someValue = "All your base are belong to us!";
}
2) The second version you wrote is better. It contains the function on the app which is good, but it can still break from some minifiers.
app.controller("MyController",function( $scope ){
$scope.someValue = "All your base are belong to us!";
});
3) To make it better, lets do this instead. Note that the function is now inside a list with its dependencies. This "double" naming of the dependencies helps angular keep track of things in minified code.
app.controller("MyController", ['$scope', function( $scope ){
$scope.someValue = "All your base are belong to us!";
}]);
4) You can also inject your dependencies after your controller, something like this. This should also be safe from minifiers as far as I know (I haven't used this version myself).
app.controller("MyController",function( $scope ){
$scope.someValue = "All your base are belong to us!";
}).$inject = ['$scope'];
So 3 and 4 are the best ones. They survive minifying and they allow you to easily mock out any dependency when writing tests. As far as I know the difference between 3 and 4 is cosmetic so both should work equally fine. I personally use 3, I think it looks slightly nicer :)
I would highly recommend the second one.
The reason behind this is minification. Angular will try to match the controller's name you call in the templates via ng-controller, e.g.:
<div ng-controller="Controller">
<!-- [...] -->
</div>
Suppose you have a controller like this:
function Controller($scope) {};
and minify it (with some minifiers), you'll get an output like this:
function c(s) {};
Quick EDIT: I checked it with uglify - it will preserve your function name (and you'll be fine), I used a maven based minifier in a project of mine, which actually mangled the method names (I guess I have to replace it)
Your app might just break from that.
Therefore it is recommended to use strings as identifiers for controllers (and injections, etc.) like this:
var app = angular.module("module", []);
app.controller("Controller", ['$scope', function(scope) {
}]);
This will stop a minifier from breaking the app. The reason to put injections like this is as follows:
var app = angular.module('module',[]);
function Ctrl($scope, $location) {
$scope.test = 42;
};
will get minified to (by UglifyJS):
function Ctrl(a){a.test=2}var app=angular.module("module",[])
and Angular will not know that you need the $scope here.
If minification does not matter to you, you can use either one, as the question really just breaks down to maintainability and readability. Also, if you have multiple modules with controllers, the second one will not get you into trouble.
The difference is that the second version defines the controller in your app space. Thus the app.controller call. Difference is that afaik you can only use the controller inside of an ng-app="yourApp" instead of everywhere on the site.
Personally, I like more the 2nd method, because it is easier to review the code and it is more maintainable, those are just my thoughts.But with 1st method you can put it as a controller in other apps.
Here is what I found from
http://www.bennadel.com/blog/2421-Creating-AngularJS-Controllers-With-Instance-Methods.htm
In most AngularJS demos, you will see Controllers being defined as free-standing JavaScript functions:
function MyCtrl( $scope ){
$scope.someValue = "All your base are belong to us!";
}
These functions are then referenced in the View using the ngController directive:
<div ng-controller="MyCtrl">
{{ someValue }}
</div>
NOTE: You should never ever abbreviate "Controller" as "Ctrl". I am only doing that here because this it is what you will typically see in a demo. You should try to avoid abbreviations as much as humanly possible when naming things in programming.
The expression used to define the ngController directive is the name of the Controller in your dependency injection (DI) framework. In an AngularJS application, the dependency injection framework is provided directly by AngularJS. This means that, rather than using a free-standing function, we can use the AngularJS controller() method to define our Controllers:
// Define "MyController" for the Dependency Injection framework
// being used by our application.
app.controller(
"MyController",
funciton( $scope ){
$scope.someValue = "All your base are belong to us!";
}
);
Here, we are defining the controller as an identifier - MyController - and a constructor function. And, once we can do this, we can get much more fine-tuned in how we actually define our constructor function.