Angular service not initialized in lazy loaded component

80 Views Asked by At

I have an Angular app that has a component with a table. When I click on the table I want to change views with the router and pass that row to the other component. I'm using a shared injectable service to do this, however my component is lazy loaded so the service is not initialized at startup.

My solution was to create a timeout such that the component and it's service get initialized before I tell the shared service to pass the row that was clicked on. Is this the best solution? Code snippet below.

onRowClicked(row: any) {
    // first let's switch to the review application view so the sharedService gets initialized
    this.router.navigate(['review']);

    // give it 100 milliseconds to initialize then pass the selected row to the sharedService
    setTimeout(() =>{
      this.sharedService.change(row); // pass selected item
    }, 100);

  }
2

There are 2 best solutions below

5
Naren Murali On

You can just change the service to be providedIn: 'root', this will ensure all the modules have the same instance of the service!

Please ensure you do not import SharedService to any of the providers array in modules or components! because this will create separate instances and your service wont be a single instance.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class SharedService {

  constructor() { }

}

Also when you navigate, there is a promise that is returned, you can just add the service code in the then block of the promise of navigate, this might also help to solve your issue!

onRowClicked(row: any) {
    // first let's switch to the review application view so the sharedService gets initialized
    this.router.navigate(['review']).then(() => {
        // give it 100 milliseconds to initialize then pass the selected row to the sharedService
        setTimeout(() =>{
            this.sharedService.change(row); // pass selected item
        }, 100);
    });
}
0
Sam Scholefield On

I would suggest a BehaviorSubject for this use case. Super basic example given below:

// shared.service.ts

public selectedRow: BehaviorSubject<Row | null> = new BehaviorSubject(null)

// table.component.ts

private sharedService = inject(SharedService)

onRowClicked(row: Row) {
  this.sharedService.selectedRow.next(row);
  this.router.navigate(['review'])  
}

// review.component.ts

private sharedService = inject(SharedService)
public row!: Row | null

ngOnInit(): void {
 this.row = this.sharedService.selectedRow.getValue();
}