Angular 17: Standalone components and not a root service

  Kiến thức lập trình

How can I provide a service that is not at the root of the application, and use the same instance between several components and other services? Not using providers in routes and not using ng module.

I’ve tried Environment injector, but didn’t get any result

6

You can create a Singleton pattern to create a class

Imagine a simple service

@Injectable()
export class DataService {
  count:number=0;
  constructor(private httpClient:HttpClient){}
  getData()
  {
    return this.httpClient.get('assets/data.json')
  }
}

We can to have a class ServiceFactory

export class ServiceFactory
{
  private static instance:DataService
  public static create(httpClient: HttpClient)
  {
    if (!this.instance)
      this.instance=new DataService(httpClient)

    return this.instance;
  }
}


See that have a property dataService create as new DataService(httpClient) and the component not inject the data service else use serviceFactory.create() and a getter dataService that will be the serviceFactory.dataService

We can use this ServiceFactory to give value to a variable dataService in the way

@Component({
  selector: 'one',
  standalone: true,
  imports:[JsonPipe],
  template: `
  <h1>one</h1>
    <button (click)="dataService.count=dataService.count+1">
         {{dataService.count}}
    </button>
    <button (click)="click()">getHttp</button>
    {{result|json}}
  `,
  
})

export class One {
  serviceFactory!:ServiceFactory
  result:any;
  constructor(httpClient:HttpClient)
  {
    this.serviceFactory=ServiceFactory.create(httpClient)
  }
  get dataService()
  {
    return this.serviceFactory.dataService
  }

export class One {
  dataService!:DataService
  constructor(httpClient:HttpClient)
  {
      this.dataService=ServiceFactory.create(httpClient);
  }

  click(){
    this.dataService.getData().subscribe({
      next:(res:any)=>this.result=res,
      error:()=>console.log("error")
    })
  }
}

Another component that use the same share the “serviceFactory” and the dataService of the serviceFactory.

One component like

@Component({
  selector: 'three',
  standalone: true,
  template: `...`,
  providers:[DataService]
  
})
export class Three {
  result:any;
  constructor(public dataService:DataService){}
}

have his own instance of the service

I know it’s a bit work-around, but this is the stackblitz

UPDATE a more Angular way

If we create a function dataServiceProvider

export const dataServiceProvider = (httpClient:HttpClient)=>
        ServiceFactory.create(httpClient);

We can use provider with useFactory, so our componets like:

@Component({
  selector: 'one',
  standalone: true,
  imports:[JsonPipe],
  template: `...`,
  providers:[{provide:DataService,useFactory:dataServiceProvider,
              deps:[HttpClient]}]
  
})
export class One {
  //we inject in constructor 
  constructor(public dataService:DataService){}
}

a new stackblitz

Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website Kho Theme wordpress Kho Theme WP Theme WP

LEAVE A COMMENT