Angular, Web

Demystifying a few Angular2 concepts for starters

8 min read

Being immersed in the JavaScript frameworks world can be intimidating. Today, I will try to demystify a few concepts and perhaps at the same time answer some questions that someone starting with Angular2 will most probably have. The framework is mature enough at this point in time to be able share some of the basics, but useful, things that one should have in mind when using it.

Angular2 uses TypeScript

TypeScript is a subset of JavaScript that is strongly typed, unlike JavaScript which is dynamically typed. Without going into too much details, it basically means that the compiler will not let you put a type into another. For instance, assigning a number (may it be a short, int, double, etc) to a string variable will not be allowed. This is not as intuitive for JavaScript programmers that are used to reusing their variables and assigning anything in them.

Your application will most probably use libraries. Since Angular2 is strong typed, it will need those libraries Type Definitions (typedefs). Think of type definitions like it is an outline of book. They are used by the compiler to understand the types (whether they be classes, methods, and even variables) of the code you are using. Some libraries include their type definitions, some don’t. This is why it is important to install them.

What you should do

Install the “@types” using npm:

Let’s not forget

Typings used to be (and can still be) used to install type definitions. However, the way described above is more of a unified way to install type definitions as it does not require you to install extra tools. If you wish to use typings you can.

To install typings as a global package, run the following command:

Typings will let you install type definitions. They look for the type definitions in this GitHub repo and have a very big extent of libraries. The popular ones are definitely there.

Once installed you can type the following to look for the available type definitions for a particular library:

For more details on how to use typings, navigate to their GitHub (link above!) and read their quick start.

Note
If you have a basic tsconfig.json (typescript config file for the compiler), it will look for type definitions files (*.d.ts) in the current working directory, its children and even parent directories. This is what TypeScriptLang has to say about it:

By default all visible “@types” packages are included in your compilation. Packages in node_modules/@types of any enclosing folder are considered visible; specifically, that means packages within ./node_modules/@types/,../node_modules/@types/, ../../node_modules/@types/, and so on.

You can, however force it to look for them at specific locations by modifying your tsconfig.json configuration file:

Remember that if you do put this in your config file, only packages under typeRoots will be included.

Observables cleanup

One of the cool things about Angular2 is the fact that they integrated rxjs into their framework. Observables are great, but can cause a lot of problem if they aren’t cleaned up or disposed properly.

What you should do

When you subscribe to an observable, the return value is a Subscription. You should unsubscribe the subscription to dispose of the resource when your component is destroyed/unmounted. If you do not, you may eventually have some memory leak in your application and to the far extent start encountering some performance problems. Therefore it is important that, in the ngOnDestroy, you call the unsubscribe method on the subscription object. The following example describes this concept.

Can we achieve the same thing in perhaps a better way?
The answer is yes. The above solution is good. However, the number of subscription objects that you have to keep in your class can grow quite exponentially if you have a lot of component/data interaction. A solution I tend to use is to declare a variable in your class that is a condition that is used to determine whether to continue to consume the observable stream or not. This behavior can be achieved by chaining the takeWhile operator to your method call as seen below.

Edit (2017-03-22):

As pointed out by CSP (thanks buddy!) in which refers back to the angular documentation, the cleanup has to do a lot with the scope/lifetime of your component. If you have a provider (a service) that you use in a component, such service will be instantiated when the component will be instantiated. Thus, when the component is destroyed, the service and all its references will also be destroyed because the component controls the lifetime of the service. So the disposal is not necessary.
However, if your component is a child component of a parent component (this means that you used a selector tag (i.e child-component) in another component (i.e parent-component)), the dispose of the subscription is a memory-leak guard step as long as your component has the same lifetime as the application itself (which may not always be the case as in for instance if you have global services in your AppModule).
In my opinion
(and also pointed out by someone in the link CSP provided), you never know when a component will be a child component, so as a best practice, it’s good to cleanup the subscriptions.

Observable “caching” with publishReplay and refCount operators

So you have a service that fetches a set of data, but you want to cache that data locally so that you don’t have to always fetch data from your server. There is no “caching” method on the Observable object provided by rxjs. However, you can simulate caching by using the publishReplay and refCount operators. The publishReplay operator basically will “replay” n times to the newly subscribers the values it has emitted where n, the parameter that the method takes, is the number of emissions to keep. The refCount operator will keep itself connected as long as there’s at least 1 subscription to it. Since you keep the subscription in your service, the values will be kept. To understand, I’ve provided an example below.

Note: do not abuse this as this can drastically deteriorate your application.

The use of the json pipe for debugging

Debugging is an essential part of our job. Sometimes, you may want to just list the value of your objects to see if they contain the right data. With the json pipe it is possible to do so. It basically converts your object value into string using JSON.stringify. Here’s an example taken from the Angular2 documentation on how to use the pipe.

The output of the above example would look like the following

Component re-usability/separation using Input/Output properties

@Input and @Output are great properties to use in your components when you want to reuse some code or separate some code (always on the road to the S in S.O.L.I.D!; Single Responsibility Principle)

@Input property

This property is useful to pass data into a component. You can use the component attributes to pass data.

@Output property

This property is used to get data out of your component back to the parent component. Generally used when you have events in your component that you want the parent to take action on. In the example below, I use the property along with the EventEmitter which is used to emit events.

Ways of doing Forms

Angular2 offers 2 ways of doing forms: the template driven way and the model-driven way. Those 2 ways introduce ways to help and most definitely ease the input validation checks of the form data values.

Template driven

Pascal Precht from Thoughtram.io has provided an excellent post on what is template driven forms and how to use them. As he mentioned, the template driven forms is a great way to build forms using limited code (JavaScript).

Model driven (or reactive forms)

Model driven follows or builds on top of the approach of template driven. However here, the ngForm is defined through code using our definitions. It can be built using the FormBuilder class found in the ReactiveFormsModule in @angular/forms module.
Pascal Precht again provided an excellent introduction to model driven forms.

One of the reason this model is interesting is that it gives you a better control on the FormControls and FormGroups of your forms and since this is code, it can be unit tested. You can also subscribe to the valueChanges property to listen to data changes in the form so you can take action, if needed. One thing to be aware of is that even though the ngModel directive do work in the Model driven style, it is highly unrecommended to use it, as the FormBuilder with its underlying FormControls, have the values stored internally and in fact acts as your model. You can access the values of the form by access the value property of the FormBuilder object.

Where is window?!

Since Angular2 uses TypeScript, window is not a known type. To use the global window variable, we must create a wrapper or in better terms a service.

The window global variable will now be available through Dependency Injection as a provider. I suggest you add it to your AppModule providers. You can then use it by passing it into your components constructor and accessing the nativeWindow property of the service class.

Help! It doesn’t work

Having a hard time to figure something out? Create a Plunker! I created a template for you to use so you don’t have to do all the setup stuff. Feel free to use it as a base to build your question. This can easily be shared around communities such as StackOverFlow or GitHub for people to see the code and see the behavior.

Conclusion

I am having fun building Single Page Applications (SPAs) and learning the perks of Angular2. Google has made a phenomenal job to ease up concepts and help developers create awesome applications. As my expertise for such framework is growing, I wanted to share what I had used and learned to help a few to get started. There are obviously more concepts and things to learn, and I hope to cover them in a future post.