Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I 'observe' the dynamic children of a component?

I have an application in which I compose forms using several form components. Now I want to create some kind of a foreign key field which lists the already existing objects and also shows an 'add' button. This button displays another form component in a modal dialog. That 'sub' form is simply displayed using <ng-content>. This all works perfectly

I'll illustrate the situation. This is the template of <form-component>:

<form class="form">
    <form-field>
        <another-form-component (save)="handleSave()"></another-form-component>
    </form-field>
</form>

The template of <form-field>:

<modal-dialog-component [(visible)]="showForm">
    <!--
        Here the <another-form-component> which was passed
        to <form-field> is added:
    -->
    <ng-content></ng-content>
</modal-dialog-component>
<div class="form-field">
    <select> <!-- existing options --> </select>
    <button (click)="openForm($event);">Create new</button>
</div>

As you can see <another-form-component> has an @Output() for it's save event. This is an EventEmitter.

My question is: How can I subscribe to this EventEmitter from the <form-field> component? I would like to know when the form is saved so I can close the <modal-dialog>.

Remember: The form is passed using <ng-content>. Can I use @ViewChildren to get the children of <form-field> and use some sort of addEventListener() method? Does something like that even exist?

Hope you can help me!

Greetings, Johan

like image 842
Johan Avatar asked Nov 09 '22 03:11

Johan


1 Answers

You can query ContentChildren from your <form-field> component class and subscribe to events they emit as following:

export class FormFieldComponent implements AfterContentInit {

    @ContentChildren(AnotherFormComponent) anotherFormComponents: QueryList<AnotherFormComponent>;

    ngAfterContentInit() {
        console.log('anotherFormComponents: ', this.anotherFormComponents.toArray());

        this.anotherFormComponents.toArray()[0].save.subscribe(valueEmitted => {
            console.log('Value emitted from the anotherFormComponents[0]: ', valueEmitted);
        });
    }
 }

QueryList gets updated whenever the AnotherFormComponent is added, removed, or moved. You can 'observe' the changes by subscribing to the QueryList.changes Observable:

ngAfterContentInit() {
    this.anotherFormComponents.changes.subscribe(qList => {
        console.log('Changed list: ', qList);
    });
}

Btw, it's worth knowing: What's the difference between @ViewChild and @ContentChild?

like image 115
seidme Avatar answered Nov 14 '22 22:11

seidme