13

I have a button in a child form component and in the from parent component I want to push a function to the child component when the onClose() function is clicked from within the child component. I've tried the method below but the issue is it will work on the first form but not the rest. I would also like to pass other functions as well, including a onSubmit. For me to proceed I will need to figure out what i'm doing wrong here. I've been at this for a few days now any help is appreciated.Thanks

child form component, in the template url it contains the button for Onclose()

import { Component, OnInit, NgModule, Input, ViewChild, Output, EventEmitter } from '@angular/core';
import { FormGroup, FormBuilder, FormControl, Validators, AbstractControl,  ValidatorFn,Form } from '@angular/forms';
import { BsDatepickerConfig } from 'ngx-bootstrap/datepicker';

@Component({
    selector: 'app-editgraphs',
    templateUrl: './editgraphs.component.html',
    styleUrls: ['./editgraphs.component.scss']
})
export class EditgraphsComponent implements OnInit {
    @Input() eGraphtitle: string;
    @Output() close: EventEmitter<any> = new EventEmitter();
    graphDataForm: FormGroup;
    constructor(private fb: FormBuilder,){}
    ngOnInit(): void {
     this.graphDataForm = this.fb.group({
    sDepartment: new FormControl(null, [Validators.required])
      });

      }

            onClose() {this.close.emit();}
            onClose2() {this.close.emit();}


parent component

import { Component, Inject, OnInit, ViewChild, ViewChildren } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { debug } from 'util';
import { EditgraphsComponent} from './../../../shared/forms/editgraphs/editgraphs.component'

@Component({
    selector: 'app-payments',
    templateUrl: './payments.component.html',
    styleUrls: ['./payments.component.scss']


})
export class PaymentsComponent {
    @ViewChild(EditgraphsComponent) private graphComponent: EditgraphsComponent;
    //graph modal titles
    egraph1Title: string = 'YTD Comparison Data';
constructor() {}

onClose() {

    this.graphComponent.graphDataForm.reset();
    console.log('Resseting and closing YCPC graph.');
}


onClose2() {

    this.graphComponent.graphDataForm.reset();
    console.log('Resseting and closing CMCPG graph.');
}

Parent Template URL


<app-editgraphs #graphComponent  [eGraphtitle]="egraph1Title" (close)="onClose($event)"></app-editgraphs>
    <app-editgraphs #graphComponent  [eGraphtitle]="egraph2Title" (close)="onClose2($event)"></app-editgraphs>

1 Answer 1

30

Function parameter approach

You can pass a function like an @Input like this.

Parent component

export class PArentComponent {

  fn = function() {
    console.log('hello');
  };
}

Parent template

 <app-child [function]="fn"></app-child>

Child component

export class ChildComponent implements OnInit {

  @Input() function: any;

 ngOnInit() {
       this.function();
 }
}

EventEmitter Approach

If you need to execute a function that needs to access parent scope variables you could choose an event approach. Contrary to @Input you can use @Output that is the angular way to communicate events from child to parent.

You can define an event in your child component like this:

export class ChildComponent implements OnInit {

 @Output() onClose = new EventEmitter();

 ngOnInit() {
 }

 closeModal() {
   // DO SOMETHING

   // emit event onClose
   this.onClose.emit();
   // you can pass also some payload into the event
   this.onClose.emit('all closed');
 }
}

Child template

<button (click)="closeModal()"></button>

Then in your Parent Component's template you can catch child component's event like all other events in angular:

<app-child (onClose)="execOnClose($event)"></app-child>

This piece of code intercepts an onClose event with (onClose) and executes parent component's execOnClose() method.

So let's look at the parent component

export class ParentComponent {

  execOnClose($event: any) {
    // DO SOMETHING
  }
}
7
  • when I try to call this from the modal form pop up close button. I get Unable to get property 'graphDataForm' of undefined or null referenceTypeError: Object doesn't support property or method 'function'. I tried this way before the problem is it calls the functions once the parent component is loaded. that's not the desired affect. I want it to only be called when I press the close button.
    – ceyon67
    Commented Aug 7, 2018 at 13:54
  • thanks for your help so far but even though the function is passed to the other child form it doesn't reset the form just the first one that called. I'm calling 2 + instances of the child component. I know the simple thing to do is just create multiple child components with the same form data but that will lead to a lot of duplicated code.
    – ceyon67
    Commented Aug 7, 2018 at 16:57
  • I can't undestand which problem you have with the EventEmitter Approach: passing data to event you can switch into your parent function and achieve whatever you want
    – firegloves
    Commented Aug 8, 2018 at 8:05
  • i have a button for <app-form (close)="onClose($event)> on close works fine then i call from another button <app-form (close)="onClose($event)> the second one the event to reset the form doesn't work but it will pass a string to console. I'm not understanding why it works for the first one and not the second.
    – ceyon67
    Commented Aug 8, 2018 at 14:09
  • 1
    @NandaKishoreAllu you have to remove the parenthesis. with parenthesis you are invoking the function, without parenthesis you are passing it for reference. so you need something like: <child [fun]="someFn"></child>
    – firegloves
    Commented Aug 6, 2019 at 7:53

Not the answer you're looking for? Browse other questions tagged or ask your own question.