I am trying to reduce code repetition with my directives. I would like to write a helper function that generates the directives instead of defining them manually. Changing the directive definition to something like:
mydirectiveBuilder(function myButton(){
return {
scope: {
toggle: "#pressed"
}
};
});
I am not sure where this should go (other then hanging it off window). Does angular provide a place for these sorts of methods to go?
Angular doesn't provide anything, but uses angular as a namespace for its own helper functions. You could simply do the same:
var myApp = (function() {
// private function, not visible from the outside
function privateFunction() {
...
}
function mydirectiveBuilder() {
...
// you can use privateFunction here
}
return {
mydirectiveBuilder: mydirectiveBuilder;
};
})();
And in your directives:
myApp.mydirectiveBuilder(function myButton(){
return {
scope: {
toggle: "#pressed"
}
};
});
You could either do what #JB Nizet suggests or if you don't like the idea of exposing something like myApp to the global scope, you just put the function somewhere and then wrap everything in a closure as a build step.
File: directiveHelpers.js
function myDirectiveBuilder(){
}
File: someDirective.js
myDirectiveBuilder(function myButton(){
return {
scope: {
toggle: "#pressed"
}
};
});
Then as a build step you concat all files and as a final build step you put a closure around it so it essentially becomes:
File: app.js
(function(){
function myDirectiveBuilder(){
}
myDirectiveBuilder(function myButton(){
return {
scope: {
toggle: "#pressed"
}
};
});
})();
This technique is used by Angular itself throughout the code base.
Another way to go about this is to attach say a UTIL object containing your helper functions to the root scope. This is captured in this tutorial
angular.module("app", ["ngResource", "ngRoute"]).run(function($rootScope) {
//app util functions
$rootScope.UTIL = {
toFilename: function(filename) {
return filename
.toLowerCase()
.replace(/ /g,'-')
.replace(/[^\w-]+/g,'');
},
fromFilename: function(filename) {
return filename
.toLowerCase()
.replace(/[^\w ]+/g,'')
.replace(/ +/g,'-');
}
//etc more functions here...
};
}
And then you can call the helper functions like;
$scope.UTIL.toFilename( filename );
$scope.UTIL.fromFilename( filename );
etc...
Snippets credit to the AngularJS4U post (link above).
I'm against putting these utils in global scope, which is a very bad practice. One option I found reasonable is to use service to declare these utils and then use inject them as dependencies as needed. This is similar to import libraries as need without polluting global scope.
angular.
module('phonecatApp').
factory('strHelpers', [
function () {
return {
snippingStr: function(str) {
return str.substring(1,20) + "...";
}
}
}])
Usage:
function usage(strHelpers) {
console.info("Demonstrating console.log and helper function: " +
strHelpers.snippingStr("111111111122222222223333333333"));
}
This is suggested by Matt Way here:
Where is a good place to put a few small utility functions in AngularJS?
Here is a simple, compact and easy to understand method I use.
First, add a service in your js that will be dedicated to receive your helper functions.
app.factory('Helpers', [ function() {
// Helper service body
var o = {
Helpers: []
};
// Dummy function with parameter being passed
o.getFooBar = function(para) {
var valueIneed = para + " " + "World!";
return valueIneed;
};
// Other helper functions can be added here ...
// And we return the helper object ...
return o;
}]);
Then, in your controller, inject your helper object and use any available function with something like the following:
app.controller('MainCtrl', [
'$scope',
'Helpers',
function($scope, Helpers){
$scope.sayIt = Helpers.getFooBar("Hello");
console.log($scope.sayIt);
}]);
Related
I need to execute functions of some controllers when my application ends (e.g. when closing the navigator tab) so I've thought in a service to manage the list of those functions and call them when needed. These functions changes depending on the controllers I have opened.
Here's some code
Controller 1
angular.module('myApp').component('myComponent', {
controller: function ($scope) {
var mc = this;
mc.saveData = function(objectToSave){
...
};
}
});
Controller 2
angular.module('myApp').component('anotherComponent', {
controller: function ($scope) {
var ac = this;
ac.printData = function(objects, priority){
...
};
}
});
How to store those functions (saveData & printData) considering they have different parameters, so when I need it, I can call them (myComponent.saveData & anotherComponent.printData).
The above code is not general controller but the angular1.5+ component with its own controller scope. So the methods saveData and printData can only be accessed in respective component HTML template.
So to utilise the above method anywhere in application, they should be part of some service\factory and that needs to be injected wherever you may required.
You can create service like :
angular.module('FTWApp').service('someService', function() {
this.saveData = function (objectToSave) {
// saveData method code
};
this.printData = function (objects, priority) {
// printData method code
};
});
and inject it wherever you need, like in your component:
controller: function(someService) {
// define method parameter data
someService.saveData(objectToSave);
someService.printData (objects, priority);
}
I managed to make this, creating a service for managing the methods that will be fired.
angular.module('FTWApp').service('myService',function(){
var ac = this;
ac.addMethodForOnClose = addMethodForOnClose;
ac.arrMethods = [];
function addMethodForOnClose(idModule, method){
ac.arrMethods[idModule] = {
id: idModule,
method: method
}
};
function executeMethodsOnClose(){
for(object in ac.arrayMethods){
ac.arrMethods[object].method();
}
});
Then in the controllers, just add the method needed to that array:
myService.addMethodForOnClose(id, vm.methodToLaunchOnClose);
Afterwards, capture the $window.onunload and run myService.executeMethodsOnClose()
I am trying to inject a few helpers (lodash and a few of my own) in Angular controllers so I have:
angular.module('app').factory("_", Lodash);
Lodash.$inject = ['$window'];
function Lodash($window) {
if ($window._)
return $window._;
}
angular.module('app').factory("_", Helper);
Helper.$inject = ['$window'];
function Helper($window) {
return {
test: function () {
return "test";
}
}
}
So I would like all helpers to be accessible under _ and I would define them in a few JS files ... Can this be done?
With my code only one of them work: lodash methods or test().
For services that don't require dependencies ($window isn't crucial here because it serves for no purpose and can be replaced with window or _ global) config block is a good place to define them, because constant services are already available there.
app.config(function ($injector, $provide) {
var lodash = $injector.has('_') ? $injector.get('_') : {};
angular.extend(lodash, window._);
$provide.constant('_', lodash);
});
app.config(function ($injector, $provide) {
var lodash = $injector.has('_') ? $injector.get('_') : {};
angular.extend(lodash, {
test: ...
});
$provide.constant('_', lodash);
});
When the service is defined this way, its value can be extended several times, the order of config blocks doesn't matter.
Alternatively, service value can be changed with decorator, in order to do that the service should be already defined.
You can not redeclare a factory. As you already noticed, this will overwrite the previous.
You could prepare the helper in separate files and register them in one factory call elsewhere in your app.
I have create a mixin component using requirejs like so:
define(function() {
'use strict';
var MyClass = function () {
console.log('Hello World');
};
return {
doSomething: function () {
var m = new MyClass();
return m;
}
}
});
My question is that is it better to write this mixin where the return is a function that can be included without accessing the returned object?
So the above would be rewritten like:
define(function() {
'use strict';
var MyClass = function () {
console.log('Hello World');
};
return function doSomething() {
var m = new MyClass();
return m;
}
});
And then when you include this module, you can then just call doSomething() versus having to include the module and access the method like myModule.doSomething().
I know that either way is acceptable, but just wanted to get an opinion on implementation.
I think it depends on agreed conventions in your project as well as on code structure. The second example probably seems more SOLID to me since every module or class should be just single responsibility. Retrurning object notation could tend to more functions on the module returning level. Just a thought though.
What is the way to create private methods in an AngularJS controllers?
I have currently done it like this, but I wonder whether it is the correct/preferable way:
app.controller('MyController', function($scope){
myPrivateFunction();
anotherPrivateFunction();
...
$scope.someScopeMethod = function(){
...
anotherPrivateFunction();
...
};
$scope.anotherScopeMethod = function(){
...
myPrivateFunction();
...
};
...
function myPrivateFunction(){
//
}
function anotherPrivateFunction(){
//
}
});
This is correct. Your functions will only be visible inside the scope of your controller constructor function. This is the same for factories and vanilla js where functions declared in functions will only be visible in their parent function context.
In factories it would looks like as below:
.factory('my-factory', function(){
function privareMethodA() {
}
var anotherPrivateMethod = function() {
}
return {
publicMethodA = function() {
},
publicMethodB = function() {
}
};
});
So after you inject your factory into another factory or a controller publicMethodA() and publicMethodB() will be available, but privateMethodA() and anotherPrivatemethod() won't be accessible from outside of this factory.
Accessibility of controllers are similar to your snippet.
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?