Change Detection: Use OnPush Change Detection per default
OnPush Change Detection only updates a component when:
- The component's input changes (e.g. a property is set by the parent component)
- An event is emitted in the component's template
- New data is emitted by an Observable that is subscribed to by the async pipe in the component's template
OnPush Change Detection has two benefits:
- It improves performance by only updating the components that need to be updated.
- It facilitates good development practices (use of immutable data structures, preferring reactive/declarative programming, building smaller components, etc.)
Lern more about the benefits of OnPush in this video.
import { ChangeDetectionStrategy, Component } from '@angular/core';
@Component({
selector: 'app-example',
templateUrl: './app-example.component.html',
styleUrls: ['./app-example.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ExampleComponent {
// ...
}
Environment: Import the EnvironmentService rather than environment.ts directly.
In order to use variables from environment.ts, you need to import the EnvironmentService.
Directly importing environment.ts leads to components that are hard to test. This is because you can't mock environment.ts.
import { EnvironmentService } from '@app/core/services/environment.service';
export class MyComponent {
constructor(private environmentService: EnvironmentService) {}
someMethod(): string {
return `Value of someKey is ${this.environmentService.get('someKey')}`;
}
}
Forms: Use typed forms by initializing them in the constructor.
Starting with Angular 14, typed forms have become the new standard.
We should initialize our form directly in the constructor, rather than using the ngOnInit
lifecycle hook.
A common pattern was to have a form member variable and initialize it within the ngOnInit
method.
This is no longer advised, as you'd have to explicitly define the type of the member variable.
Instead, simply initialize the form in the constructor when defining the member variable to let Typescript infer the
type.
import { FormGroup, NonNullableFormBuilder, Validators } from '@angular/forms';
export class MyComponent {
form: FormGroup<{ email: FormControl<string> }>;
constructor(private fb: NonNullableFormBuilder) {
this.fb.group({
email: ['', [Validators.required, Validators.email]],
});
}
}
It's advised to use the NonNullableFormBuilder
instead of the default FormBuilder
so the default values are being used instead of fields being null
when the form is reset.