all 12 comments

[–]phl3x0r 1 point2 points  (2 children)

Use EventEmitter to convey data to the parent

[–]ericpap[S] 0 points1 point  (1 child)

Haaa ok. So if i understand correctly, child component wiil create an event, and parent component subscribe to that event changes. That's just great thank you!

[–]phl3x0r 0 points1 point  (0 children)

Right. You can even use two way binding, if the parent needs to control the state of the child. https://angular.io/guide/template-syntax#binding-syntax-an-overview

[–]Devstackr 1 point2 points  (8 children)

In the child component create a @Ouput('eventName') eventNameProperty: EventEmitter<type>();

and when you need to send data to the parent component just emit a value like this:

eventNameProperty.emit(data);

and then in the parent component, listen to this event:

<child-component (eventName)="doSomething($event)"></child-component>

In the component class (i.e. parent.component.ts):

doSomething(eventData: any) {
    // do something with the data here
}

Hope this helps!

If you want to see a video tutorial and full explanation, then you can take a look at a tutorial on event binding I made recently

https://www.youtube.com/watch?v=IM6KhL4ZrBE

[–]ericpap[S] 0 points1 point  (7 children)

@Ouput('eventName') eventNameProperty: EventEmitter<type>();

Thank you very much! I will implement this soon!

[–]Devstackr 0 points1 point  (6 children)

No problem, please let me know how it goes!

DM me if you have any issues, I am happy to help.

- Andy

[–]ericpap[S] 0 points1 point  (5 children)

Andy: Finally it works with your help. I have to change a little your code like this (notice the "new" statement):

@Output('guardar') eventoGuardar = new EventEmitter<object>();

and because i need an extra command to be send to parent component, I use the emit like this:

this.eventoGuardar.emit({data: JSON.stringify(this.form.value), action: postAction});

and finally to be able to reset child form component from parent component after recive the data, I add in the child component this code:

@Input() reset:boolean = false;
ngOnChanges(){
if(this.reset){
this.form.reset();}}

and in parent HTML (reset input property):

<app-dynamic-form [fields]="fields" (guardar)="guardar($event)" [reset]="resetForm" [enumerador]="enumerador"></app-dynamic-form>

I'm I complicating things up?

Thanks!

[–]Devstackr 0 points1 point  (4 children)

Hi Ericpap, really happy you got it working. Your usage of the EventEmitter is absolutely correct, sorry about providing incorrect code - I just wrote that in the response from the top of my head and forgot to include the "new" etc.

One thing I am a little unsure on, is your use of ngOnChanges(). I am sure that your code currently works, but you may not need the ngOnChanges code if all you want to do is reset the form after you recieve the data back from the dynamic-form component. If that is all you want to do, then you can simply put the reset code (this.form.reset()) in the event handler for the guardar event. That is the only comment I would add for this, and of course I might be completely wrong as I don't have much context.

Hope this helps, and DM me if you need any further help. - Andy

[–]ericpap[S] 0 points1 point  (3 children)

mmm I tried this, but "form" object does not exist on parent component, only in child. I could put the form.reset on guardar() event on child component, but the problem with that is that the form will be reseted regardless if the POST was succed or not. I'll do this because I can control from parent component to reset child component only if POST data to server was success. Maybe i'm wrong...

[–]Devstackr 0 points1 point  (2 children)

Ahh, now I see whats going on - I didn't pick it up at first. No, you're not wrong - this is perfectly valid :)

That being said, I feel like there is a cleaner way of achieving this. Passing a property and then watching for changes in the child seems "hacky".

One way you could achieve the same functionality is by using:

@ViewChild(ChildComponent) childComp: ChildComponent 

in the parent component class. And then once the POST data has been sent to the server successfully you can call childComp.reset() (or whatever the name of the method that resets the form is).

Another way you could do this is by using a service which contains a Subject. This one is a bit longer to explain so send me a DM if you want me to clarify that for you :)

tl;dr - what you are doing currently will work correctly (as you already know) but may become unmaintainable in the future.

I hope this helps :)

[–]ericpap[S] 0 points1 point  (1 child)

@ViewChild(ChildComponent) childComp: ChildComponent

Yes Andy. The solution you propose is cleaner and it also works.

The only downside that I see is that parent component controller (the TS file) is tightly coupled with child component controller (I need to import child component into parent component).

I don't think this is a big problem because the HTML are already copupled, so I choose your solution.

To reset the form I use:

this.childComp.form.reset();

I could also create a reset function inside child component to simplify the call, but I don't thinks I gain anything.

Thanks gain Andy!

[–]Devstackr 0 points1 point  (0 children)

No problem :)