简体   繁体   中英

Open same angular component as different instances at the same time

I have angular component that has a list with dataSource is subscribed from a BehaviourSubject from the service.

In the list.component.html template file:

<ng-container *ngFor="let item of items;">
    <h2>item.name</h2>
</ng-container>

In the list.component.ts file:

ngOnInit(): void {
  this.service.items$.subscribe(data=>{
      this.items = data;
 });
}

On clicking the item in the list, it loads the sub items for the selected item in the same table.

Now, I have a button side this component that will open a MatDialog window.

This MatDialog windows should contain the same component mentioned above.

What I have tried:

I have created a wrapper for this component and opened the Wrapper in the MatDialog.

wrapper.component.html

<div>
 <app-list></app-list>
</div>

Inside list.component.html opening the WrapperComponent in MatDialog:

this.matDialog.open(WrapperComponent);

Everything works fine until i click on the list item inside the matDialog.

The selected item is loaded isnide the list in the matDialog. But at the same time in the background the orginal ListComponent is also loading the same value. Becasue, the subscribed value from BehaviourSubject is updated when clicked on the item in the list.

this.service.updateListValue = updatedValue;

The original ListComponent is loaded with router module and resolver.

How can i avoid this? How to open the same component but as two different instances?

To inject a service class inside multiple modules as multiple instances:

what you can do this,

in your service class @Injectable

Replace : @Injectable({ providedIn: 'root' })

With : @Injectable({ providedIn: 'any' })

When providedIn: 'root' option is used, the angular injector will make your service class act as a singleton and there will be only one instance of this service for the entire application.

When providedIn: 'any' option is used, the Angular injector will instantiate a new service for each module that injects this service .

Bonus: If a Class ServiceA is being used only by ModuleA, you can use

@Injectable({ providedIn: ModuleA }) . This will be optimal when you have a service that is being used only by Single module

Reference: NG0201

To inject a service class to multiple components inside the same module as multiple instances:

The answer by @misha130 could work too.

In order to have a service specific for the component you need to provide it in the @Component decorator metadata. This will create an instance of the service for each component instance.

@Component({
    providers: [SomeService],
})

Your service should not be providedIn root as well.

@Injectable()

If you want to use the same component and different metadata you can have 2 different service implementations based on the module.

You can declare a token that would represent the service

export const SERVICE_TOKEN: InjectionToken<SomeService> = new InjectionToken<SomeService>('Some Service Token');

Then in each module specify which service you want to inject:

  providers: [
    {
      provide: SERVICE_TOKEN,
      useClass: SomeServiceA,
    },

Afterwards in the constructor of the component inject it like so:

   constructor(@Inject(SERVICE_TOKEN) private readonly someService: SomeService){}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM