Angular 2: как передать значение из одного компонента, чтобы обновить другой компонент при обнаружении изменений?

Поэтому я использую тип ng2-bootstrap для поля поиска, которое у меня есть. Когда я выбираю возвращаемое значение, я хочу, чтобы панель ниже обновлялась с подробностями, полученными из выбранного элемента.

В моем родительском компоненте у меня есть это:

HTML:

<input [(ngModel)]="asyncSelected"
                           [typeahead]="dataSource"
                           (typeaheadLoading)="changeTypeaheadLoading($event)"
                           (typeaheadNoResults)="changeTypeaheadNoResults($event)"
                           (typeaheadOnSelect)="onSelectSearchValue($event)"
                           [typeaheadOptionsLimit]="7"
                           [typeaheadMinLength]="3"
                           [typeaheadWaitMs]="500"
                           [typeaheadOptionField]="'name'"
                           name="searchField"
                           class="form-control" style="width: 250px;" placeholder="Search Chip Families">
...
<div class="container-fluid">
    <router-outlet></router-outlet>
</div>

Машинопись:

public onSelectSearchValue(e: TypeaheadMatch): void {
    this.chipFamilyId = e.item.id;
}

Как получается, что я передаю это значение, возвращаемое из заголовка, моему компоненту, который обрабатывает вызов службы, чтобы найти детали и поместить их в <router-outlet>? Использование обнаружения изменений, похоже, не сработало.

Мой дочерний компонент выглядит следующим образом:

HTML:

<div class="content" *ngIf='chipFamilies && chipFamilies.length'>
    <ol class="breadcrumb">
        <li><a [routerLink]="['/home']">Home</a></li>
        <li><a [routerLink]="['/chipFamily']">{{chipFamilies.Hierarchy}}</a></li>
        <li class="active">{{chipFamilies.Name}}</li>
    </ol>
    <h2>{{chipFamilies.Hierarchy}}</h2>
...

Машинопись:

export class ChipFamilyComponent implements OnInit, OnChanges {
    errorMessage: string;
    @Input() chipFamilyId: number = 11223;
    chipFamilies: IChipFamily[];

    constructor(private _adminService: ChipFamilyService) {

    }

    ngOnInit(): void {
        //Initially load 11223 on load
        this._adminService.getChipFamily(this.chipFamilyId).subscribe(
            chipFamilies => this.chipFamilies = chipFamilies,
            error => this.errorMessage = <any>error
        );
    }

    ngOnChanges(changes:{[propKey: string]: SimpleChange}) {
        debugger;
        this._adminService.getChipFamily(this.chipFamilyId).subscribe(
            chipFamilies => this.chipFamilies = chipFamilies,
            error => this.errorMessage = <any>error
        );
    }
}

person occasl    schedule 16.11.2016    source источник
comment
@Input() предназначен для связи между прямыми родительско-дочерними компонентами. В вашем случае у вас есть <router-outlet> посередине, так что этот тег больше не актуален. Вместо этого вы должны использовать общую службу и Subject для запуска события изменения в отдельных компонентах.   -  person Harry Ninh    schedule 16.11.2016
comment
См. также angular.io/docs/ts/ последняя/поваренная книга/   -  person Günter Zöchbauer    schedule 16.11.2016


Ответы (1)


Из отличного предложения Harry_Ninh я придумал, как разрешить связь между компонентами без использования @Input и любые селекторы компонентов:

В своем сервисе я добавил тему, чтобы родитель мог объявить о том, что поиск был выполнен:

@Injectable()
export class ChipFamilyService {
    private searchStringSubject = new Subject<string>();
    private _searchUrl = 'http://localhost:8888/chipfamily/'; 

    constructor(private _http: Http) {
    }

    searchAnnounced$ = this.searchStringSubject.asObservable();

    announceSearch(searchValue: string) {
        this.searchStringSubject.next(searchValue);
    }

В моем родительском компоненте я только что сделал объявление после того, как результат был выбран из моего поля ввода:

public onSelectSearchValue(e: TypeaheadMatch): void {
    this.chipFamilyService.announceSearch(e.item.id);
}

В моем дочернем компоненте я подписываюсь на объявление, а затем обновляю модель на основе новых данных в конструкторе:

@Component({
    template: require('./chip-family.component.html')
})
export class ChipFamilyComponent implements OnInit {
    errorMessage: string;
    chipFamilyId: number = 11223;
    chipFamilies: IChipFamily[];
    private gridOptions:GridOptions;
    subscription: Subscription;

    constructor(private chipFamilyService: ChipFamilyService) {
        this.subscription = chipFamilyService.searchAnnounced$.subscribe(
            chipFamilyId => {
                this.chipFamilyId = Number(chipFamilyId);
                this.chipFamilyService.getChipFamily(this.chipFamilyId).subscribe(
                    chipFamilies => this.chipFamilies = chipFamilies,
                    error => this.errorMessage = <any>error
                );
            });

    }

Это позволяет достичь желаемого результата обновления панели просмотра новыми данными на основе поиска по опережающему вводу.

person occasl    schedule 16.11.2016