How to make a reusable AngularJs components - angularjs

This seems like it should be easy, but I can't find documentation on it. I'm wondering how to make an Angular component (let's say a filter) reusable in different apps. I've made a simple filter that formats a phone number, and I'd like to be able to use it in any app. Currently it is declared like this:
var myModule = angular.module('myModule', ['ngSanitize']);
myModule.filter('formatFilter', function() {
return function(input) {
return input.replace(/(\d{3})(\d{3})(\d{4})/, "($1) $2-$3");
}
});
The question is how to make this filter reusable. Right now it's just attached to 'myModule', but how can I take it out of this file so I can reuse it elsewhere too?

You started OK by encapsulating your filter in a separate module. For other apps to use it, those apps will just need to include source code of your filter and declare dependency on a module:
angular.module('myApp',['myModule'])
You would probably like to rename your filter-holding module to something more meaningful, something like phoneFormatter or sth.

Just as an example :
This is a reusable filter declared as a module, so only needs to be injected on the app:
Filter:
angular.module("lov-filter", []).filter('StartOnPage', function () {
return function (input, start) {
start = +start;
return input.slice(start);
}
});
App:
var demoApp = angular.module('demoApp', ['lov-filter'])
.config(function () {
});
Used on this angular directive: https://github.com/rolandocc/lov-angular-directive

Related

Create custom Angular filter without app name

How to create custom angular filter without angular app name?
// usual way for creating filter
var app = angular.module('app', []);
app.filter('makeUppercase', function () {
return function (item) {
return item.toUpperCase();
};
});
app.controller('PersonCtrl', function () {
this.username = 'Todd Motto';
});
I only know creating angular filters with app name.
My concern is how we can create a filter without app name and inject it into a controller. Does it possible to create a javascript function and pass these to controller.
You will always need to attach your filter to some module, in your case var app = angular.module('app', []); is a module and you making a filter inside that module.
You can use the filter inside your controller like below:
app.controller('PersonCtrl', function ($filter) {
this.username = 'Todd Motto';
var caps = $filter('makeUppercase')("make me caps");//call your filter like this
});
Yes you can do that.
You can create a module and then create a service containing the filter.
After that you can inject that newly created module to your module and use the filter.
To add a filter through a service you can read this answer.

AngularJs - Best way to include my service inside every controller?

I'm building a small two-language app with the use of angular-translate. I want to have a language switcher in every view (controller). I'm trying to figure out how to put the code responsible for language switching into every controller. The code looks like this:
var langSwitch = $Scope.setLang = function (langKey) {
$translate.use(langKey);
};
So far I've figured that I can create a factory that looks like this:
app.factory('langSwitch', function ($rootScope, $translate) {
var langSwitch = $rootScope.setLang = function (langKey) {
$translate.use(langKey);
};
return langSwitch;
});
and inject it into controllers in this maner:
app.controller('HomeCtrl', function (langSwitch) {
// normal controller code here
});
This works but 1) I'm using $rootScope and I have a feeling this is bad practice & 2) jsHint screams that "langSwitch" is not defined. Maybe there is a simpler way to make the function global without putting it into every controller?
I'm still pretty new to Angular so don't scream at me :) Thanks.
edit
My view:
<button ng-click="setLang('en_GB')">English</button>
<button ng-click="setLang('pl_PL')">Polish</button>
Although you got the idea, you overcomplicated things a bit. You could declare the service as follows:
app.service('langSwitch', function ($translate) {
this.setLang = function (langKey) {
$translate.use(langKey);
};
});
And then inject langSwitch in the controller responsible for lang switching, as you already did. No need to inject $rootScope in the service.
You don't need $rootScope indeed unless you need to process some global events in your application. All services and factories in angular are singletons by default. That means once it created, it will be passed as the same instance in every place it is declared as a dependency. So if you want to share data and functionality between different controllers - the services will suit fine. You can change your factory code to:
app.factory('langSwitch', function($translate) {
return {
setLang: function(langKey) {
$trasnlate.use(langKey);
};
};
});

Adding an array of controllers to module in AngularJS : The Best way

I just went through a code where the programmer has created an array of controllers and then added the array to a module.
Following is the type of code :-
// the array of controllers
var controllers = {};
//adding a controller to array
controllers.ExampleController1 = function(){};
controllers.ExampleController2 = function(){};
//adding the controllers to module
var ABCmodule=angular.module('ABCmodule',[]);
ABCmodule.controller(controllers);
I realized that the controller array is made in global scope. Isnt that dangerous? Moreover is this good style of coding. I prefer only making one variable for module and adding all controllers inside that module. What is the best way to do this?
This particlar setup can be solved by:
for (var ctrl in controllers) {
if(controllers.hasOwnProperty(ctrl)) {
ABCmodule.controller(ctrl);
}
}
That being said, why not just add controllers directly to module which would be declared first? Also loop can be simplified using lodash's _.forOwn()
angular
.module('abc', [])
.controller('ctrl1', ctrl1)
.controller('ctrl2', ctrl2); // ...
function ctrl1() {
}
function ctrl2() {
}
Angular does this internally all the time, but you don't have to accept its source code style as paragon. It is ok while you keep the variables inside IIFE.
If you want to keep the style in ng vein, you can do like this:
ctrlModule.config(function ($controllerProvider, controllers) {
angular.forEach(controllers, function (constructor, name) {
$controllerProvider.register(name, constructor);
});
});
ctrlModule.constant('controllers', { ... });

Possible to inject a complete module in Angular?

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.

AngularJS - what are the major differences in the different ways to declare a service in angular?

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?

Resources