2017-05-15 13 views
5

Mam element nadrzędny zawierający listę komponentów podrzędnych. Te dzieci są tworzone dynamicznie i mogą być dowolnego rodzaju.Subskrybuj zmiany w składniku macierzystym w Angular

Co robię, używając ng-container jako hosta w komponencie nadrzędnym, utwórz komponenty potomne za pomocą ComponentFactoryResolver, a następnie zaktualizuj niektóre właściwości komponentu potomnego, używając `` `(component.instance jak każde) .id = host.id; `` ``

Oto kod dla elementu nadrzędnego (jest to stół z kilkoma rzędami):

<tr class="table-collapse__item" [class.active]="company === selected"> 
    <td [attr.colspan]="getItemColspan()"> 
    <ng-container host [id]="name" [selected]="isSelected"></ng-container> 
    </td> 
</tr> 

host jest dyrektywa

@Directive({ 
    selector: '[host]' 
}) 
export class Host implements OnChanges { 
    @Input() id: any; 
    @Input() selected: boolean; 
    constructor(public viewRef: ViewContainerRef) {} 
} 

i wreszcie jak tworzyć komponenty i zaktualizować właściwości

@ViewChildren(Host) hosts: QueryList<Host>; 

    constructor(private resolver: ComponentFactoryResolver, 
       private cd: ChangeDetectorRef) {} 

    ngAfterViewInit() { 
    if (this.hosts) { 
     const componentFactory = this.resolver.resolveComponentFactory(this.inner); 
     this.hosts.forEach((host: Host) => { 
     const component = host.viewRef.createComponent(componentFactory); 
     (component.instance as any).id = host.id; 
     (component.instance as any).selected = host.selected; 
     }); 
     this.cd.detectChanges(); 
    } 
    } 

Teraz moje pytanie. Potrzebuję komponentu potomnego do reagowania na zmiany jego właściwości, ale ponieważ jego właściwości nie są wejściami, ale tylko podstawowymi właściwościami, nie mogę używać ngOnChanges wewnątrz childComponent. Czy istnieje sposób, w jaki mogę zasubskrybować komponent potomny do zmian w komponencie nadrzędnym?

Mogę używać polecenia ngOnChanges w dyrektywie Host i aktualizować właściwości w komponencie, ale jak wywołać pewien kod w komponencie potomnym?

Mam do przetestowania plunker. Klikając na dane1, dane2, dane3 lub dane4, poniższy wiersz powinien zwinąć się lub rozwinąć.

Dzięki.

Odpowiedz

3

elementy podrzędne nie mogą słuchać zmian w rodzica, ale można je powiadomić o zmianach, wywołując metodę na dzieciach zamiast:

components = []; 
ngAfterVeiwInit() { 
if (this.hosts) { 
    const componentFactory = this.resolver.resolveComponentFactory(this.inner); 
    this.hosts.forEach((host: Host) => { 
     const component = host.viewRef.createComponent(componentFactory); 
     (component.instance as any).id = host.id; 
     (component.instance as any).selected = host.selected; 
     this.components.push.components(); 
    }); 
    this.cd.detectChanges(); 
    }  
} 

ngOnChanges() { 
    this.components.forEach((c) => { 
    c.instance.ngOnChanges(); // or any other method the child comonents have 
    }) 
} 
+0

Dzięki! ale pojawia się błąd podczas wykonywania tego '' 'TypeError: innerComponents [this.id] .ngOnChanges nie jest funkcją''' będącą innerComponents tablicą, którą zasugerowałeś w swojej odpowiedzi. Mój ChildComponent implementuje OnChanges, ale sposób. – David

+0

Co to jest 'this.id'? Czy składniki faktycznie mają metodę 'ngOnChanges'? Brakuje również ".instance". –

+0

Przepraszam, masz rację, brakuje .instance. Działa teraz, dzięki! – David

0

Można użyć emiterów zdarzeń w składniku dzieci i dostęp do funkcji w składniku dominującej

https://angular.io/docs/ts/latest/api/core/index/EventEmitter-class.html https://toddmotto.com/component-events-event-emitter-output-angular-2

+0

Nie, właściwość, która zmienia się w komponencie potomnym, nie ulega zmianie s przez komponent podrzędny, ale przez rodzica, więc nie mam sposobu, aby wiedzieć, kiedy to się zmieni w komponencie potomnym. – David

Powiązane problemy