Sébastien Lucas / Dev wiki
  • Blog Wiki
  • Story book
  • Developers comics
  • Angular
    • Angular CLI + Angular.json
    • ngTemplateOutlet
    • Angular Schematic
    • Interceptor
    • Micro frontend + Mono repo
    • Build a library module
    • Error handling
    • Virtual and infinite scroll
    • Angular i18n
    • Debug Angular
    • Angular LifeCycle Hook
    • Nested forms in Angular
    • Angular Recipes
    • Master component in Angular
    • Perfomance optimization
    • Service Workers + PWA
    • Mobile
    • Electron app / Desktop app
    • Unit test & Angular
      • Unit test recipes (Jasmine / Karma / Angular)
      • Testing services with httpMock
    • Communication between components
    • Angular snippet library
    • Release and version management
    • Angular tutorial selection
    • UI components libraries
    • Angular libraries
    • Angular Tutorials
    • NGRX
      • Angular NGRX / Tips and code examples
      • Angular new Redux (alternative to ngrx)
      • NGRX unit test
      • Angular ngrx / Basics
    • Angular 2/Angular 1 differences
  • Graphql
  • Three.js
  • Ag grid
  • Open source BIM and 3D
  • Javascript
    • Null vs undefined
    • Html API
    • Await API
    • Debug memory leaks
    • Offline and PWA
    • Javascript tutorials
    • Javascript recipes
    • Bluebird missing docs
    • Alternative to lodash with ES6
    • ES6 syntax the best parts
    • Vanilla JS
  • RXJS
    • Docs
    • Recipes
    • Mock API and sandbox
    • Observables rxjs recipes
    • Combination operators
  • NODE.js
    • Environment variables
    • Fix CORS
    • Pagination requests in API
    • API tests
    • Node.js security
    • Learn node.js
    • Best libraries for node.js
    • Mongoose recipe
    • Debug node.js
  • Gatsby / React
    • Hooks
    • React concepts
    • Gatsby internationalisation
  • Ghost blog
  • Services for developers
    • SaaS images services
    • Airtable API examples
  • MISC
    • JIRA debugging
    • Wordpress plugins
    • Interview Sébastien Lucas
    • English expression
    • True recipes
    • Science podcast
  • AI
    • Machine learning open source
    • Tensor flow
    • Machine learning
    • Code examples
    • Courses and tutorials
    • Datasets
    • The Future of AI
    • Learn algo and data structures
  • Typescript
    • Generic types
    • Typescript recipes
    • Advanced types
      • Conditional types
      • Type guards
    • d.ts files
  • Docker
    • Starting with docker
    • Dockerise simple node app
    • Docker by aymen el amri
  • Mongodb
    • Pattern and data modeling
  • Devops
    • Heroku
    • Scaleway
    • Github template
    • Gitlab CI
    • http2
    • nginx
    • zsh
    • CI Continuous integration
    • DNS
    • Devops resources
    • Gcloud useful commands
    • Authenticate Gcloud
    • Documentation generators
    • Firebase database
  • Developers ressources
    • Online platform coding
      • Online courses
      • Coding games
      • Coding test platforms
      • Links to check
    • Good developers blogs
    • Nice open source project / github
  • Tooling
    • The chrome urls
    • Linux Mac tips
    • Webstorm configuration
    • Develop in Windows
    • Mac debug hardware
    • Mac Setup for a developer
    • Chrome extension
    • Develop toolbox
  • HTML / CSS
    • Tailwind
    • Css grid
    • ☘️Nice styles & generators
    • Favicon
    • Flexbox grid
    • Flexbox layout
    • PUG templates tips
    • Html and css references
    • Css snippets
    • SASS-CSS libraries
    • New things in scss
    • SASS best practices
    • Style lint
  • Tests
    • Cypress
      • Learn cypress and more tests
      • Cypress commands
      • Cypress plugins
      • Page object && app actions
      • Flaky tests
    • Mobile test
    • BDD + Cucumber
    • Puppeteer
    • Type of tests + Ressources
    • Jasmine test
    • Mock, fake, stub in unit tests
    • E2e tests with protactor
    • Mocha
  • REVIT & AEC tools
  • Git
    • Git commits
    • Git tips
    • Git hooks
    • Set up a mono repo
  • Design Pattern
    • Functional Programming
  • Job board / Remote jobs
  • SVG
  • JSON
  • Github
    • Forking a github repo
  • NPM
    • Private NPM packages
    • Publish to NPM with np
  • Yarn
    • Yarn evolution / 2, 3...
    • Yarn Linking
Powered by GitBook
On this page
  • Elvis operator and bracket notation
  • Select an element of the DOM
  • Prevent error when module are failing to be imported
  • Object property binding & async pipe with bracket syntax
  • Instantiating a class or static method
  • Simplify module definition with the spread operator
  • Export of modules to be compatible with lazy loading, AOT and universal angular
  • Navigate to a defined page in the component or service
  • Do somethings after 2 or more promises resolve
  • Redirect to the same path but changing one query params
  • Redirect to the same path changing only the last path parameter
  • watching queryparams and params changes
  • Execute a js library outside of the scope of angular
  • Add even, odd and last class to ngFor
  • Dynamic templates
  • Injection parent component in child component
  • Http interceptor
  • Execute a function with a delay in an angular component
  • Use environment variable in your component or service
  • Async handling automation and Progressive Web app
  • Sharing data / method between component
  • Setup of universal server side rendering (updated)
  • Angular Forms : setValue vs patchValue
  • Return a mock if server is off
  • Multiple service calls
  • Router lazy load nested path

Was this helpful?

  1. Angular

Angular Recipes

Some tips and tricks for specific cases in Angular

PreviousNested forms in AngularNextMaster component in Angular

Last updated 4 years ago

Was this helpful?

Tips & tricks for tricky but useful things in angular 2. The type of problems that are too small to deserve a full blog post, and that you do not know how to name to search for.

Elvis operator and bracket notation

Bracket notation is javascript is an alternative to dot notation to display the content of an object. The main advantage is has is that you can use variable inside the bracket to display a property whose name depends of a variable.

Elvis operator is a syntax for angular 2 that allow telling angular renderer to ignore template binding of sub-properties for object that does not exist yet. Indeed, it is generally that the object is not yet loaded from the backend.

From this

The Elvis operator is only available for the . notation, not for other operators like []. As a workaround use

data?.record ? data.record['name/first'] : null

Select an element of the DOM

Well explained

Use ViewChild with #localvariable as shown here,

<textarea  #someVar  id="tasknote"
                  name="tasknote"
                  [(ngModel)]="taskNote"
                  placeholder="{{ notePlaceholder }}"
                  style="background-color: pink"
                  (blur)="updateNote() ; noteEditMode = false " (click)="noteEditMode = false"> {{ todo.note }}

</textarea>

In component,

//OLD Way
import {ElementRef} from '@angular/core';

@ViewChild('someVar') el:ElementRef;

ngAfterViewInit()
{
   this.el.nativeElement.focus();

}

New API with renderer....

//NEW Way
import {ElementRef} from '@angular/core';

    @ViewChild('someVar') el:ElementRef;


constructor(private rd: Renderer) {}

  ngAfterViewInit() {
    this.rd.invokeElementMethod(this.el.nativeElement,'focus');
  }

Prevent error when module are failing to be imported

Module handling in JS is a headache. Sometimes it just don't works. But you still need to use a js lib the old way (with a script in the index.html).

You can fool typescript to allow you to use the missing library (that will exist at run time).

declare var braintree:any;

Object property binding & async pipe with bracket syntax

Yes but how to use a bracket syntax with async syntax.

I have an observable that I want to pass to a component. Once passed I want a sub property that is static in that case : the first item of an array. Or may be dynamic, a component property.

The problem is that : (imagesFB | async)[0] would fail because the item does not exist at first and the async is for imagesFB not for the resulting array that (imagesFB | async) return.

So with a ternary syntax :

 (bolean) ? /* code if true */ : /* code if false */ ;`

We do the trick.

ui-gallery-image([image]="(imagesFB | async) ? (imagesFB | async)[0] : null")

Instantiating a class or static method

There are 3 keywords that can be used in a class. To defined a property or method

  • public to get the method available from other classes

  • private to get it only usable inside the class

  • static allow to use a class without instantiating it

    Instantiate a class, is creating a local copy of it. For example if we are in a component, that mean that we are using an instance of a class.

    An instance is creating by passing it to the component constructor like this.

import { UploadService }         from '../../../services/api/upload.service'

export class UiUploadUploadcareComponent {
  constructor(
    private uploadService: UploadService,
  ){
  }

  upload() {
    // we use the instance of the class with this
    this.uploadService.upload()
  }

But by using static we do not need, and we cannot actually create a local instance

import { StaticService }         from '../../../services/static.service'

export class UiUploadUploadcareComponent {
  constructor(
    // we do not need to instanciate the class
  ){
  }

  upload() {
    // we use the static method useStaticClass
    // of StaticService  class without the this keyword
    StaticService.useStaticClass()
  }

Simplify module definition with the spread operator

@NgModule({
  imports: [
    ...MODULES
  ],
  declarations: [
    ...PIPES,
    ...COMPONENTS
  ],
  exports: [
    ...MODULES,
    ...PIPES,
    ...COMPONENTS
  ]
})

Export of modules to be compatible with lazy loading, AOT and universal angular

const PIPES = [
  // put pipes here
];

const COMPONENTS = [
  // put shared components here
];

const PROVIDERS = [
  ModelService,
  ApiService
]

@NgModule({
  imports: [
    ...MODULES
  ],
  declarations: [
    ...PIPES,
    ...COMPONENTS
  ],
  exports: [
    ...MODULES,
    ...PIPES,
    ...COMPONENTS
  ]
})
export class SharedModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: [
        ...PROVIDERS
      ]
    };
  }
}

Navigate to a defined page in the component or service

import { ActivatedRoute, Router }           from '@angular/router';

// Component definition

constructor(
    private router: Router,
    private route: ActivatedRoute,
  ) {}

// Inside a component method

this.router.navigate([], { queryParams: {step : this.order.step}, relativeTo: this.route });

Do somethings after 2 or more promises resolve

Usage of Rxjs Observable.combineLatest to do something and combine the results of the 2 or more promises resolved.

import { Observable } from 'rxjs'

Observable.combineLatest(
      this.translationService.getTranslation("reset_title"),
      this.translationService.getTranslation("reset_desc")
    )
    .subscribe(results => {
      // DO something
    })

Redirect to the same path but changing one query params

The trick is [] to tell same page.

this.router.navigate([], { relativeTo: this.route, queryParams: { step: this.steps[0] } });

Redirect to the same path changing only the last path parameter

The trick is to use relative path syntax of angular 2 router

// change orderId only while we are at order/22 for example
// but keeping all parameters
this.router.navigate(['../', this.order._id], { queryParams: this.params, relativeTo: this.route });

// For this  path (defined in routing configuration)
{ path: 'order/:orderId', component: SROrderPage },

watching queryparams and params changes

  • queryparams are optional ?step=2&lang=fr so step and lang

  • params are in the path /project/:projectId so project Id in that cas

For both we use the Activated route service, so we place in our constructor

constructor(
    private route: ActivatedRoute) {}

then we set a watcher in our ngInit()

ngOnInit() {
      this.route
      .params
      .subscribe(routeParams => {
        // trigger when route params change
        // routeParams = { projectId: 22 }
      });

      this.route
      .queryParams
      .subscribe(queryParams => {
        // trigger when route params change
        // project/22?lang=fr
        // queryParams = { lang: 'fr '}
      });

  }

Execute a js library outside of the scope of angular

Angular run inside an execution context so is not accessible in the global scope of the page. But some libraries like jQuery exist in the global scope of the page.

Import of the NgZone module

import {
    Component, Input, Output, EventEmitter, NgZone, forwardRef, AfterViewInit,
    OnDestroy, Directive, ElementRef, Host
} from '@angular/core';

Definition in the component constructor

constructor(private el: ElementRef, private zone: NgZone) {

Use of this.zone.runOutsideAngular(() => {

to switch execution zone

   /**
     * init slick
     */
    initSlick() {
        const self = this;

        this.zone.runOutsideAngular(() => {
            this.$instance = $(this.el.nativeElement).slick(this.config);
            this.initialized = true;

            this.$instance.on('afterChange', (event, slick, currentSlide) => {
                self.zone.run(() => {
                    self.afterChange.emit({event, slick, currentSlide});
                });
            });

            this.$instance.on('beforeChange', (event, slick, currentSlide, nextSlide) => {
                self.zone.run(() => {
                    self.beforeChange.emit({event, slick, currentSlide, nextSlide});
                });
            });

            this.$instance.on('breakpoint', (event, slick, breakpoint) => {
                self.zone.run(() => {
                    self.breakpoint.emit({event, slick, breakpoint});
                });
            });

            this.$instance.on('destroy', (event, slick) => {
                self.zone.run(() => {
                    self.destroy.emit({event, slick});
                });
            });
        });
    }

Add even, odd and last class to ngFor

div(
    *ngFor="let item of item; let last = last; let odd = odd; let even = even; let index = index;",
    [ngClass]="{'odd': odd,'even': even,'last': last}", 
    class="item item-{{ index }}")

will result in

<div class="item odd item-1">
First item
</div>
<div class="item even item-2">
Second item
</div>
<div class="item odd last item-2">
Third item
</div>

Dynamic templates

Injection parent component in child component

  • @ContentChildren() allow to have a reference to a child component in the parent component

  • @Host() allow to have a reference to a parent component in the child component

@Directive({
  selector: '[slick-carousel-item]',
})
export class SlickCarouselItem {
  constructor(private el: ElementRef, @Host() private carousel: SlickCarouselComponent) {
  }
  ngAfterViewInit() {
    this.carousel.addSlide(this);
  }
  ngOnDestroy() {
    this.carousel.removeSlide(this);
  }
}

Http interceptor

Http interceptor intercept http requests for example to add a token to all API request.

Define interceptor service in the app.module.ts

Example of interceptor file

Execute a function with a delay in an angular component

Use environment variable in your component or service

Async handling automation and Progressive Web app

Sharing data / method between component

Setup of universal server side rendering (updated)

Angular Forms : setValue vs patchValue

Return a mock if server is off

getTasks(): Observable<Tasks[]> {
    return this.httpClient
      .get<Tasks[]>(URL.forTasks())
      .pipe(catchError(() => of(TASKS_MOCK)));
  }

Multiple service calls

Router lazy load nested path

For query params read this for more info

So here is an example on .

In angular 2 your can use dynamic templates called by name Primeng library make heavy use of it, you can see as an illustration

Example and explanations in the tutorial

`

link
here
http://stackoverflow.com/questions/36803389/angular2-async-pipe-not-does-not-fill-object-data-into-template
Doc of spread operator
good tuto
how to run a jquery library from an angular component
templates definitions here
slick-carousel integration
https://medium.com/beautiful-angular/angular-2-and-environment-variables-59c57ba643be
https://medium.com/@cyrilletuzi/angular-async-pipe-everywhere-with-ngx-pwa-offline-d8de68845c81
https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/
https://angularfirebase.com/lessons/server-side-rendering-firebase-angular-universal/
https://ultimatecourses.com/blog/angular-2-form-controls-patch-value-set-value
Angular Multiple HTTP Requests with RxJS - Angular 13 | 12coryrylan
How to Nest Lazy-Loaded ModulesMedium
Logo
Logo