12/08/2018, 16:04

Several bad practices in Angular

About 5 months after the ground-breaking release of Angular 2, the next huge update for Angular has become now available: Angular 4 (or Angular due to the development team's concensus that it should be called Angular solely from now on without stating the version number explicitly. At the ...

About 5 months after the ground-breaking release of Angular 2, the next huge update for Angular has become now available: Angular 4 (or Angular due to the development team's concensus that it should be called Angular solely from now on without stating the version number explicitly. At the first place, the “2” was intended to differentiate between AngularJS and the all brand-new Angular Framework, which was introduced with many reassessed and refined concepts.

Indeed, Angular is really awesome. Not only does it provide hell of a lot functionalities out of the box (routing, animations, HTTP module, forms/validations and etc) but also speeds up the development process and most importantly, Angular is really not that hard to learn and embrace (especially with such a powerful tool as Angular CLI).

But like they often says, "a good instrument in incautious hands might one day become a nuclear weapon of mass destruction", thus the topic that I would like to present today shall be several ways and practices in Angular which I suggest you definitely NOT use.

2.1. Not making a REAL use of Angular components

In an Angular ecosystem, components are the essential building blocks serving as the bridge which connects between application's logic and view. But there are occasions that developers strongly overlook the benefits a component provides. Let us consider this example:

@Component({
  selector: 'app-form-control-component',
  template: `
    <div [formGroup]="form">
      <div class="form-control">
        <label>Job Postion</label>
        <input type="text" formControlName="jobPosition" />
      </div>

      <div class="form-control">
        <label>Salary</label>
        <input type="text" formControlName="salary" />
        <span>(USD)</span>
      </div>

      <div class="form-control">
        <label>Qualification required</label>
        <input type="text" formControlName="qualification" />
      </div>
    </div>
  `
})
export class CreateJobComponent implements OnInit {
  
  form: FormGroup;
  
  constructor(private formBuilder: FormBuilder) {

  }
  
  ngOnInit(): {
    this.form = formBuilder.group({
      jobPosition: [', Validators.required],
      salary: [', Validators.required],
      qualification: [', Validators.required]
    });
  }
}

As you can see, we have a little form with three controls, and a template which contains the actual inputs. Each input is put inside a div element, alongside with its label, and the three containers repeat themselves. They are essentially the same, so, maybe, separate them into a component? Now take a look at this:

@Component({
  selector: 'app-form-control-component',
  template: `
    <div class="form-control">
      <label>{{ label }}</label>
      <input type="text" [formControl]="control" />
      <span *ngIf="unit">({{unit}})</span>
    </div>
  `
})
export class SingleControlComponent{
  @Input() control: AbstractControl 
  @Input() label: string;
  @Input() unit: string;
}

So, we have separated a single control to it’s own component, and we have defined inputs to pass data from the parent component, in this case, the form control instance and the label of the input. Let’s revise our first component’s template:

<div>
  <app-form-control-component [control]="form.controls['jobPosition']" [label]="'Job Position'"></app-form-control-component>

  <app-form-control-component [control]="form.controls['salary']" [label]="'Salary'" [unit]="'USD'"></app-single-control-component>

  <app-form-control-component [control]="form.controls['qualification']" [label]="'Qualification'"></app-form-control-component>
</div>

As you reach this part, you might probably think “well, component separation is a basic Angular concept, why would you have you make such simple thing seem bizarre? Everyone knows this, duh...”, but the problem is that many developers are deceived by Angular’s router module: it maps a route to a component, and therefore, people (mostly newbies, but sometimes it happens with more experienced devs too) have the tendency to treat these components as of separate pages. Angular component is NOT a page, it is a piece of the view, and several components together compose a parent view.

Another nasty situation is when you have a small component, mostly without any specific logic at the beginning, however, as new requirements arrive, it just grows larger and larger inevitably. In the nick of time, you had better start thinking of component separation, otherwise, you may end up with an uncontrollable, ugly monstrosity version of the component.

2.2. Abusing .toPromise()

Angular comes with its own out-of-the-box HTTP module for our app to communicate with remote servers. As you should already know by now that Angular uses Rx.js to support HTTP requests, instead of Promises. You know what? The fact is that not everyone is aware of the existence of Rx.js. True. Nevertheless, if you are going to use Angular for a long-term project, it is suggested learning it. Those who are new to Angular tend to just transform Observables returned from API calls in the HTTP module to Promises by using .toPromise() due to their familiarity with Promise. To be honest, that is probably the worst thing you can do to your application, because just for the sake of your laziness you:

  1. Add unnecessary logic to your app. You don’t need to transform an Observable to a Promise, you can work with the stream of data itself. [Oservable Link]

  2. Throw away a lot of disadvantages Rx.js provides: you could cache a response, you could manipulate the data before subscribing to it, you could cancel a request response if it is no longer needed, you could find logical mistakes in the received data and rethrow errors to catch them later on in your app with just one or two lines of code… All miracles happen thanks to Observable. But you preferred .toPromise() instead             </div>
            
            <div class=

0