#angular
#angular
Вопрос:
У меня есть пользовательский компонент, который зависит от двух сервисов:
@Component({
selector: 'app-search-reon',
templateUrl: './search-reon.component.html',
styleUrls: ['./search-reon.component.scss'],
providers: [
ReonSearchState,
{
provide: SEARCH_PARAMETERS_CADNUM,
useValue: { layers: [335], types: [201, 207], helpSearch: false, searchText: '', searchType: 2 },
},
{
provide: SEARCH_PARAMETERS_ADDRESS,
useValue: { layers: [335], types: [203], helpSearch: false, searchText: '', searchType: 2 },
},
{
provide: SEARCH_PARAMETERS_UNOM,
useValue: { layers: [335], types: [202], helpSearch: false, searchText: '', searchType: 2 },
},
{ provide: SEARCH_CONFIG_CADNUM, useClass: SearchConfig, deps: [SEARCH_PARAMETERS_CADNUM] },
{ provide: SEARCH_CONFIG_ADDRESS, useClass: SearchConfig, deps: [SEARCH_PARAMETERS_ADDRESS] },
{ provide: SEARCH_CONFIG_UNUM, useClass: SearchConfig, deps: [SEARCH_PARAMETERS_UNOM] },
{
provide: ReonSearch,
useFactory: reonServiceFactory,
deps: [ReonCloudEsService, ReonSearchState],
},
],
})
export class SearchReonComponent implements OnInit {
@Input() searchType: ReonSearchType;
@Output() onSelected = new EventEmitter<any>();
public selectedObjectValue: any;
private reonSearch: ReonSearch;
constructor(
@Inject(ReonSearch) public reonServiceFactory: any,
@Inject(SEARCH_CONFIG_CADNUM) public searchCadnumConfig: SearchConfig,
@Inject(SEARCH_CONFIG_ADDRESS) public searchAddressConfig: SearchConfig,
@Inject(SEARCH_CONFIG_UNUM) public searchUnumConfig: SearchConfig,
) {}
ngOnInit() {
try {
this.factoryReonSearch(this.searchType);
} catch (e) {
console.log('ERROR:' e);
}
this.selectedObject.subscribe((value) => {
this.selectedObjectValue = value;
});
}
private factoryReonSearch(searchType: ReonSearchType): void {
switch (searchType) {
case ReonSearchType.CADNUM:
this.reonSearch = this.reonServiceFactory(this.searchCadnumConfig, searchType);
break;
case ReonSearchType.ADDRESS:
this.reonSearch = this.reonServiceFactory(this.searchAddressConfig, searchType);
break;
case ReonSearchType.UNOM:
this.reonSearch = this.reonServiceFactory(this.searchUnumConfig, searchType);
break;
default:
throw Error('No provider for search type!');
}
}
public get isLoading(): Observable<boolean> {
return this.reonSearch.isLoading;
}
public get objects(): Observable<any> {
return this.reonSearch.objects;
}
public get selectedObject(): Observable<any> {
return this.reonSearch.selectedObject;
}
public selectionChange($event: MatSelectChange): void {
this.reonSearch.setSelectedObject($event.value);
this.onSelected.emit($event.value);
}
public search($event): void {
this.reonSearch.search($event);
}
}
Только один триггер события (запрос на сервер):
public search($event): void {
this.reonSearch.search($event);
}
У этого компонента есть собственный модуль:
const modules = [CommonModule, MaterialModule, FormsModule, ReactiveFormsModule, NgxMatSelectSearchModule];
const components = [SearchReonComponent];
@NgModule({
declarations: [...components],
imports: [...modules],
exports: [...components],
providers: [ReonCloudEsService],
})
export class SearchReonModule {}
Этот модуль я импортировал в диалоговые модули, где мне нужно показать этот компонент следующим образом:
<app-search-reon [searchType]="ReonSearchType.CADNUM"></app-search-reon>
Как вы можете видеть, этот компонент использует factory для предоставления ReonSearch
объекта в компоненте.
Это выглядит так:
export class ReonSearch {
public searchEvent = new BehaviorSubject<string>(null);
public loading = new BehaviorSubject<boolean>(false);
private cadnums: any[] = [];
private addresses: any[] = [];
private unoms: any[] = [];
private response: any[] = [];
constructor(
private reonCloudService: ReonCloudEsService,
private searchConfig: SearchConfig,
private searchType: ReonSearchType,
private reonSearchState: ReonSearchState,
) {
this.searchEvent.pipe(switchMap(() => this.reonCloudService.search(this.searchConfig.parameters))).subscribe(); // REUEST TO SERVER
}
Почему каждый раз, когда я открываю любое диалоговое окно, в котором импортируется SearchReonModule
, я вижу запрос к серверу в ReonSearch
строке:
this.reonCloudService.search(this.searchConfig.parameters)
Для кого это событие this.searchEvent
? Почему Angular не создает отдельные экземпляры ReonSearch
ReonSearchState
для каждого используемого компонента?
ВАЖНО:
Я заметил, что конструктор ReonSearch
вызывается столько раз, сколько было использовано component в разных модулях (диалоговых компонентах).
ОСНОВНОЙ ВОПРОС:
Почему, несмотря на то, что у компонента есть поставщик, Angular не создает отдельные instnaces для: ReonSearch
, ReonSearchState
внутри компонента:
{
provide: ReonSearch,
useFactory: reonServiceFactory,
deps: [ReonCloudEsService, ReonSearchState],
},
И почему один компонент влияет на другие?
Кажется, я ошибаюсь, я проверил все компоненты, завод каждый раз снова работает:
export const reonServiceFactory = (reonCloudEsService: ReonCloudEsService, reonSearchState: ReonSearchState) => {
console.log('works');
}
Итак, если в tmeplate есть два компонента, я вижу три раза works
. Но что не так с this.searchEvent
? Как это влияет на другие компоненты?
Комментарии:
1. Я попытаюсь воспроизвести это в StackBlitz
2. Может быть, как-то отказаться от подписки
this.searchEvent
в конструкторе?3. Кто может объяснить мне, как создать изолированные компоненты в случае повторного использования в разных компонентах в шаблоне?