How to make a crappy app with Angular 2. Or not

Posted on Posted in Development
  • Time to read: less than 10 minutes.

If you’re currently using Angular 2, or just started using it, you will have to understand that there is a way of doing things and you should follow that line. Let me share with you my mistakes, well my experience, with you.


Pipes

Use methods to process data in html templates. Well it works that way, but this will slow your app a lot: because being a method, Angular Change Detector will call every time the method and you will see a lot of calls per second are being made. That’s why in Angular 2 you have to use only pipes when displaying data that should be processed in your html template, out of your class. Also, you can reuse the pipes in all your app components.

Warning: the application can be visible slowed down when using methods to process data in HTML templates.

import { Injectable, Pipe, PipeTransform } from '@angular/core';
/*
 * This filterByName allows me to filter an aray of objects by a certain property.
 * In our case, Name property.
 */
@Pipe({
	name: "filterByName"
})
@Injectable()
export class FilterByName implements PipeTransform {
	transform(data: any[], args: any): any{
		if(!args) {
			return data;
		}
		return data.filter(item => item.Name.toLowerCase().indexOf(args.toLowerCase())-1);
	}
}

Then, make sure you specify the Pipe to your component decorator, to be able to use it in HTML template like the example bellow:

<input type="text" [(ngModel)]="searchName" [ngModelOptions]="{standalone: true}" placeholder="Search by name" />
<li *ngFor="let person of persons | filterByName: searchName">
  {{ person.Name }}
</li>

So this is how I was able to create a listing for Persons and have a input field to allows me search by name through the entire listing, instead of using methods, and events – like (change) event for search field.


ViewChild vs EmitterService

When working with multiple components, especially parents and child components, you might need to access some data from child components in your parent component. You can make it in two different ways.

1. ViewChild

That is my recommendation that will help you to get access to the child component class and get properties or call methods. It’s very useful when your parent component can interact with the child component.

import { Component, ViewChild } from '@angular/core';
import { ProfileComponent } from './profile.component';

@Component({
    selector: 'master-app',
    directives: [ProfileComponent],
    templateUrl: '../path/to/your/template.html',
})
export class MasterComponent {
    @ViewChild(ProfileComponent) 
    private profileComponent: ProfileComponent;

    /* Now, I can access methods and properties of child component "ProfileComponent" */
    hasChanges() {
      return this.profileComponent.getChanges();
    }
}

2. EmitterService

Well, this is reactive programming. You can use the EmitterService to create channels and then subscribe to the channel to receive data when it’s sent via EmitterService using the emit call.

The EmitterService can be used then you have to be notified by a data change in order to reflect the change across your app, in multiple components at once.

ngOnInit() {
	this.subscription = ProfileEmitterService.get("has_changed").subscribe(data => {
        this.reload();
    });
}

And here is how you notify the subscriber about the change.

ProfileEmitterService.get("has_changed").emit(true);

Unsubscribe

I remember I lost about 1 hour for a bug trying to figure out why I am being redirected to another route when saving changes on the one I just edited. Well in my case, I had a reusable component with a form inside and after saving the data, I was notifying the subscribers that is time for an update, because the data has been changed: so other components can reflect the new changes.

Example: inside your app, you can edit your profile, but you can also make profile changes from multiple sections across the app. You want to subscribe to profile changes in order to reflect the update in my account widget: icon, username etc.

My mistake

Well, my mistake was very simple. I forgot to unsubscribe from EmitterService channel in ngOnDestroy  and that’s why when I was saving the form in a certain route state, I was redirected immediately to the previous route, the one without unsubscribe.

ngOnInit() {
  this.subscription = ProfileEmitterService.get("has_changed").subscribe(data => {
      this.reload();
  });
}

ngOnDestroy() {
  this.subscription.unsubscribe();
}

Be smart. Do not repeat.

I shared with you 3 ways of making your app crappy. Please, try to understand first how things works and then make sure you pay attention to not do the same mistakes I did. Otherwise, you will spend your valuable time trying to figure out what you did wrong.

Be smart!

Leave a Reply

Your email address will not be published. Required fields are marked *