What is a factory in Angular - javascript

I was reading an article of Max NgWizard K, about how Angular updates the DOM. I came across the following:
For each component that is used in the application Angular compiler generates a factory. When Angular creates a component from a factory Angular uses this factory to instantiate View Definition which in turn is used to create component View. Under the hood Angular represents an application as a tree of views.
In another article from Max NgWizard K I found the definition of a factory:
Factories describe the structure of a component view and are used when instantiating the component.
I'm not really sure what is meant with this.
Questions:
What exactly are factories in Angular(2+)?
Are there scenarios that a developer benefits form knowing how they work?

What exactly are factories in Angular(2+)?
Factory is one of the design patterns mentioned by Gang of Four (Basically they wrote a book on the design patterns they discovered).
Design Patterns help programmers solve common development tasks in a specific way.
And in this case, the Factory pattern helps in instantiation and creation of Objects.
It is also known as the Virtual Constructor.
Think of it, like this:
Say you are making a 2D shooter game, and you have to shoot bullets out of barrels.
Instead of instantiating bullets like new Bullet(), every time trigger is pulled, you can use a factory to create bullets, i.e. WeaponsFactory.createInstance(BulletTypes.AK47_BULLET).
It becomes highly scalable, since all you have to do is change the enum and the factory will make it for you.
You won't have to manually instantiate it.
That is what angular does, it automatically creates factory of all the components. Which makes its job easier.
Are there scenarios that a developer benefits form knowing how they work?
You don't have to know the inner workings of a Factory to use Angular, but it's useful for creating components dynamically!
e.g. A lot of *ngIf, or *ngSwitchCase can be replaced by a simple dynamic generation of components
Components can be created dynamically like this:
createComponent(type) {
this.container.clear();
const factory: ComponentFactory = this.resolver.resolveComponentFactory(AlertComponent);
this.componentRef: ComponentRef = this.container.createComponent(factory);
}
Reference for understanding the above code: Dynamically Creating Components

'A factory' in this case is an instance of ComponentFactory, a class that has create method that implements Factory method pattern.
When componentFactory.create is called (either directly or via ComponentFactoryResolver - which is essential for dynamic components, as linked article explains), new component instance is created.

In general factory is a creational design pattern. It is an object for creating other objects – formally a factory is a function or method that returns objects of a varying prototype or class from some method call.
From the Angular docs
#Component({
selector: 'app-typical',
template: '<div>A typical component for {{data.name}}</div>'
)}
export class TypicalComponent {
#Input() data: TypicalData;
constructor(private someService: SomeService) { ... }
}
The Angular compiler extracts the metadata once and generates a
factory for TypicalComponent. When it needs to create a
TypicalComponent instance, Angular calls the factory, which produces a
new visual element, bound to a new instance of the component class
with its injected dependency.
This is something which happens behind the scenes. But you create dynamic components using ComponentFactoryResolver as well (Dynamic component loader)
//Only dynamic component creation logic is shown below
loadComponent() {
this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length;
const adItem = this.ads[this.currentAdIndex];
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component);
const viewContainerRef = this.adHost.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent<AdComponent>(componentFactory);
componentRef.instance.data = adItem.data;
}
Also read this article about how the component factories work in Ivy.

Related

Using singleton design pattern for better code quality

We have a node-express app with multiple endpoints. We have created 5 different services that does different jobs such as making HTTP calls, process/modify data, cache data, search specific data, etc.
We realized that the services we created are not singleton. The services were being instantiated left right and center. A total of 26 objects were being created.
We changed that and made all our services singleton, and now only 5 objects get created across the entire application. We want to structure the app properly now.
We want each express route to call DataService (which checks if that data is available in the CacheService, if not then make an HTTP call and store the data in cache and return the data to the express route).
But, the current code makes use of CacheService and DataService together to check if the data is available in the cache or fetches fresh data using DataService. Which approach is recommended? Use one service (Dataservice) that internally uses multiple services (CacheService, DataModificationService), or use all the services together in the express route (DataService, CacheService, DataModificationService)
Before making the classes singleton, we were using static classes. Do we even need to make services singleton or continue to use static classes? Which one is more recommended and why?
Here's the code that we've written to create a Singleton Service . Is this the correct way?
class DataService {
private dataModificationService: DataModificationService;
private tokenService: TokenService;
private constructor(tokenService: TokenService, dataModificationService: DataModificationService) {
this.tokenService = tokenService;
this.dataModificationService = dataModificationService;
}
public static getInstance(): DataService {
const dataModificationService: DataModificationService = DataModificationService.getInstance();
const tokenService: TokenService = TokenService.getInstance();
if (!DataService.instance) {
DataService.instance = new DataService(tokenService, dataModificationService);
}
return DataService.instance;
}
}
It's good that you've reduced the number of singletons. Now try and get rid of the rest!
Changing from a static class to a singleton object often makes no difference - they're both just ways of making stuff global.
What you need to be doing is looking at how many places use each singleton, and if the usages are localised, then try to replace the singleton with dependency injection. Nothing fancy, just pass the (non static) instance of the DataService or whatever in as a parameter where needed. If that would create too much code, then what you've done is perfectly fine.

Access Singleton from anywhere

In my game, I've created a list of gameObjects (instances of other classes such as Player) in my Main that I can loop through and render in one function, rather than rendering them all individually. This is my render function;
this.gameObjects = [];
addObj(obj){
this.gameObjects.push(obj);
}
render(){
this.gameObjects.forEach(obj => obj.render());
}
This works no problem if I want to add another gameObject using my main class like this;
let main = new Main();
let player = new Player(10, 30, 10, 10, 'red');
main.addObject(player);
main.start();
However, I want to add another gameObject, called Projectile within my Player class. The problem is my Player class doesn't have access to Main's addObj function.
My idea was to create a singleton, that holds a list of game objects, like this;
class Repository{
constructor(){
if(this.instance){
return this.instance;
}
this.list = [];
this.instance = this;
}
get obj(){...}
addObj(obj){...}
}
The tl:dr of the question is;
Is this the best way to go forward?
How would I access this singleton? By importing it everywhere I needed it?
Create a global variable with an instance? How would I do this?
Am I over thinking this? Should I just pass main in to each class and access its methods that way?
Using a singleton might complicate unit tests, and add a hidden state to the information flow of the application. It's not that the pattern is inherently flawed, but there's a right and wrong way to use this pattern, and if you don't intend to spend the time and understand the pattern, you're probably better off not using it. Your plan for the Singleton will work, it's just not the most robust solution.
Notice that JS is a functional language. You don't need to pass main to each class, you can just pass the addObject function. That way when you change context (for example in unit tests or if you'll recycle the code for other projects) you'll be able to just switched the passed function, and keep all of your code.

Angular 2 Convert Function Name to Function Reference

Am moving some javascript logic into an Angular 2 app. Part of it involves a homegrown library of "formatter" functions [they do more than just formatting, so pipes are not an option] Currently these are passed by name (string) and the receiving function uses window[fName] to convert them to a function reference.
So there's a formatter function:
var tickPositionerYMD = function() { ticks=[]; ... complex logic ... return ticks; }
And a build function:
build(x, y, formatterName) {
...
formatter = window[formatterName];
...
}
And the build is called with a particular formatter:
build(xData, yData, 'tickPositionerYMD');
In javascript, window[] is used to create a function reference.
Question is ... what's the best way to do this in an Angular 2 component? Have seen one approach where a service is created with a reference to window ... this is passed in through DI.
A second approach is to create a factory function which given a name, returns a function.
Given those choices, am inclined to go with the factory function. Being new to Angular, was wondering if I might be missing a better approach.
You should use Angular services.
Each service is a singleton, so when you inject it to your components all all refferences will be pinting to the same instance.
So when you define formatters int your service, you should expose either method getFormatter(formatterName) or Map of Formatters and use it like this:
// method:
let formatter = formatterService.getFormatter('myForm');
// Map:
let anotherFormatter = formatterService.formatters['myForm']
Just don't forget that you inject services not instantiate.

Any difference between angular $inject property and inline array annotation?

Reading angular docs on dependency injection, there are two minification-friendly methods to do this:
Inline Array Annotation:
module.factory("MyStuff",['dependency',function(dep){...}])
The $inject property:
function MyStuff(dep) {...}
MyStuff.$inject = ['dependency'];
module.factory("MyStuff",MyStuff);
The inline one (first) is recommended. In one of my projects the style guide insists on the use of $inject property. I also see $inject property form quite often in open source code.
Hence the question:
What are the practical or technical benefits of using the $inject property form?
From the top of my head I came up with two, and they don't look very legit:
Creating instances of MyStuff directly:
new MyStuff(someOtherDependency).foo(...);
Having function name in console.log(myStuffInstance)
Anything else I am missing?
You should be using ng-annotate. If you are using build tool (you should), use the ng-annotate plugin with your build tool.
The main benefit of second approach is that it is module friendly.
class MyClass {
constructor($q) {}
}
MyClass.$inject = ['$q']
module.exprots = MyClass
You can use it like normal class
const MyClass = require('./myclass')
const foo = new MyClass($q)
or give it to angular
angular.service('MyClass', MyClass)
You can't really do
module.exports = ['$q', MyClass]
because it will make require('./myclass') unusable outside of angular
But if you are not using module or OOP, first approach is easier
angular.service('MyClass', ['$q', function ($q) {}])
There is no need to make a class for it

Communication between ViewModels in KnockoutJS

I'm trying to implement communication between my view models in a knockoutjs driven application. I scaffolded it using yeoman tool, and as you can see it uses AMD:
define(['knockout', 'signals', 'text!./nav-bar.html'], function(ko, Signal, template) {
function NavBarViewModel(params) {
this.route = params.route;
}
return { viewModel: NavBarViewModel, template: template };
});
I have to define an object that I would later use to dispatch events, right? Something like that:
var EventDispatcher = {
itemClicked: new Signal()
};
And then, whenever something happens in the NavBarViewModel I'd like to do:
EventDispatcher.itemClicked.dispatch();
The problem is - where should I put this EventDispatcher thing? It's obvious that it should be some kind of a global object, so that every VM could get a hold on it, but it would be ugly. Dependency injection came to mind, since everything else in this architecture I choose is done this way, but how to achieve that? I come from WPF, MVVM world, and so far I've used MVVMLight framework which had this great Messenger component. Is there anything like that in the JS world (and if it's js-signals lib I'm already using, then how should I use it to achieve my goal?)
I could also use the subscribable object built into the knockout fw, but the question still stands - where to put it (or how to share the instance between VMs)?
You'd quite simply inject it by including it in your define.
First, create a new file, EventDispatcher.js with your EventDispatcher code inside (and other relevant Knockout bits, like returning the view model and whatnot).
Then in your current file add it in:
define([ ... , ... , "EventDispatcher"], function( ... , ... , EventDispatcher )
Now you can simply call its methods within this file by using:
EventDispatcher.itemClicked.dispatch()
(Where EventDispatcher is what we've named it in our define parameters).
Do bear in mind though that your EventDispatcher.js file will also need the signals file passed to it through its own define wrapper.

Categories