Backbone.js RequireJS Mixin - backbone.js

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.

Related

How to store controller functions in a service and call them in AngularJS

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()

"this" undefined in side link function in Angular directive built with TypeScript

I'm a relative newbie to both TypeScript and Angular so I'm probably doing something very basic wrong here.
I'm trying to create an abstract base class from which I can derive multiple directives, each of which will implement a single custom validation rule. My code compiles okay, but fails at runtime, specifically when it tries to call this.isValid(...) because "this" is undefined at that point. Can anyone see what is wrong with this code?
module App.Common.Directives {
'use strict';
export abstract class ValidatorBase implements angular.IDirective {
require = 'ng-model';
restrict = 'A';
constructor(private validationErrorKey: string) { }
link(scope: angular.IScope, el: angular.IAugmentedJQuery, attributes: Directives.IValidatorAttributes, controller: angular.IFormController) {
//tsc writes "var _this = this;" here, but this is undefined
scope.$watch(attributes.ngModel, () => {
const val: string = el.val();
const valid = this.isValid(val, el, scope, attributes, controller);
controller.$setValidity(this.validationErrorKey, valid, undefined);
});
}
abstract isValid(val: any, el?: angular.IAugmentedJQuery, scope?: angular.IScope, attributes?: Directives.IValidatorAttributes, controller?: angular.IFormController): boolean;
}
}
Here is the output from the TypeScript compiler for this class:
var App;
(function (App) {
var Common;
(function (Common) {
var Directives;
(function (Directives) {
'use strict';
var ValidatorBase = (function () {
function ValidatorBase(validationErrorKey) {
this.validationErrorKey = validationErrorKey;
this.require = 'ng-model';
this.restrict = 'A';
}
ValidatorBase.prototype.link = function (scope, el, attributes, controller) {
var _this = this; //this is undefined when we get here
scope.$watch(attributes.ngModel, function () {
var val = el.val();
var valid = _this.isValid(val, el, scope, attributes, controller);
controller.$setValidity(_this.validationErrorKey, valid, undefined);
});
};
return ValidatorBase;
})();
Directives.ValidatorBase = ValidatorBase;
})(Directives = Common.Directives || (Common.Directives = {}));
})(Common = App.Common || (App.Common = {}));
})(App || (App = {}));
In Angular directives it is unsafe to consider this a class instance because functions can have their own lexical this, and they actually have it.
this is controller instance in controller (which may or may not be exposed on scope with 'controller as' syntax).
this is DDO object in compile (so this is contextual here).
this is undefined in linking functions (in strict mode).
Use arrow functions if you're unsure about lexical this or want to override it:
link = (...) => { ... };
//tsc writes "var _this = this;" here, but this is undefined
Two possible issues:
You should type _this in the debug console. This is because of the way the sourcemaps work at the moment : Chrome Typescript debugging references wrong 'this'
You are registering the directive with angular in a wrong way. Note that angular will not call new on foo if foo is used like .directive('foo',foo). Angular assumes its already a variable that has all the right stuff on it. Angular was not written with classes in mind (angular 1 is now fairly old).

TypeScript: Can't define class inside an IIFE

I want to define a class inside an IIFE using TypeScript and keeps getting error, class can be defined either in a module or a file. Below code does not work.
(function(){
// Error here
class Person {
}
})()
The reason i need to do this is because i don't want to expose any global variables, not even module. You may wonder why, because i would add them to angular modules in below way
(function(){
angular.module('app').controller('HomeController', HomeController);
// error here
class HomeController {
}
})();
When you create a class, it generates an IIFE for you:
The class:
class Example {
}
Results in the JavaScript:
var Example = (function () {
function Example() {
}
return Example;
})();
If you want to keep your classes out of the global scope, you can use modules:
module Stack {
export class Example {
}
export class Overflow {
}
}
Only the Stack module appears in the global scope.
var Stack;
(function (Stack) {
var Example = (function () {
function Example() {
}
return Example;
})();
Stack.Example = Example;
var Overflow = (function () {
function Overflow() {
}
return Overflow;
})();
Stack.Overflow = Overflow;
})(Stack || (Stack = {}));
If you want to go a step further, you can use external modules - when you do that, none of your classes or modules is added to the global scope.

Where do angular helper functions go?

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);
}]);

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