Angular2: how to call main component function from child component

How do I call a main component function from a child component when I have a deep nested hierarchy?

enter image description here

I have 3 components, a button component in which I include a browser component and a browser component that I include in a main component.

When the button is clicked, I need to call a function that is inside the main component.

Button component

@Component({
    selector: 'cb-button',
    templateUrl: 'cb-button.component.html',
    styleUrls: ['cb-button.component.scss']
})

export class CbButtonComponent {

     @Output() onClick: EventEmitter<any> = new EventEmitter();

     onBtnClick(): void {
        this.onClick.emit();
    }
}

      

html button component

<div (click)="onBtnClick()">
    <button>btn</button>
</div>

      

browser component

@Component({
    selector: 'topology-browser',
    templateUrl: 'topology-browser.component.html',
    styleUrls: ['topology-browser.component.scss']
})

export class TopologyBrowserComponent {

   @Input('campus') campus: Campus;
}

      

html browser component

<div>
<h1>browser title</h1>
<cb-button (click)="editCampus()"></cb-button>
</div>

      

and finally in the main component I include the browser component

<strong> core-component.ts

editCampus() {
  alert('clicked');
}

      

Html

<topology-browser [campus]="campus"></topology-browser>

      

when i click the button i get below error

Errorself.parentView.context.editCampus is not a function

+3


source to share


4 answers


  • If you know what type of root component is, you can use the Pengyy method.
  • If you don't know which type beforehand, but you can customize the root component to suit your needs, a generic service is a good way to go.

  • A more general way is to get the root component by injecting ApplicationRef

    (not actually tested by itself):

constructor(app:ApplicationRef, injector: Injector) {
  app.components[0].someMethodOnMainComponent();
}

      



https://angular.io/docs/ts/latest/api/core/index/ApplicationRef-class.html

+3


source


As I know there are two possibilities for your situation:

  • inject

    parent component for child component
  • use EventEmitter



Since you have more than two levels, nesting MainComponent

in is ButtonComponent

much easier to implement:

import {Component, Inject, forwardRef} from '@angular/core';

// change the MainComponent to your real component name
constructor(@Inject(forwardRef(() => MainComponent)) private main:MainComponent)

      

+2


source


export class CbButtonComponent {

     @Output() onClick: EventEmitter<string> = new EventEmitter<string>();

     onBtnClick(): void {
        this.onClick.emit('clicked');
    }
}

      

In your browser component

Html

<div>
    <h1>browser title</h1>
    <cb-button (onclick)="buttonclicked($event)"></cb-button>
</div>

      

Component

@Output() buttonClick: EventEmitter<string> = new EventEmitter<string>();

buttonclicked(clickedEvent){
   this.buttonClick.emit('clicked');
}

      

In your main component

<topology-browser [campus]="campus" (buttonClick)="buttonComponentClicked($event)"></topology-browser>

      

Component code

buttonComponentClicked(buttonClicked){
       /// method calls goes her

}

      

This way you notify the browser component with a click, which is captured again in the main component and processed

0


source


You can try the following. I haven't tried this, but I think it might work. The button component fires an event that is captured by the main component.

You can also pass data through a generic service and inject that service into a child component and call a service function that updates the observable service that is subscribed by the main component

Main component

@Component({
  template `
    <button-comp (onClick)="mainMethod($event)"></button-comp>
  `,
  directives: [ ButtonComponent ]
})
export class MainComponent {
  (...)

  mainMethod(event) {
    console.log(event)
  }
}

      

your button component

@Component({
    selector: 'cb-button',
    templateUrl: 'cb-button.component.html',
    styleUrls: ['cb-button.component.scss']
})

export class CbButtonComponent {

     @Output() onClick: EventEmitter<any> = new EventEmitter();

     onBtnClick(): void {
        this.onClick.emit('hello');
    }
}

button component html

<div (click)="onBtnClick()">
    <button>btn</button>
</div>

      

0


source







All Articles