简体   繁体   中英

How to access a method from app.component from other component?

I am new to Typescript and Angular 2. I tried to look for an answer in the web but it seems they don't work for me.

Say I have an app.component as shown below:

export class AppComponent implements OnInit {

    constructor(public _testService: TestService) { }

    listForCart = this._testService.getListForCart();
    cartCount = this.listForCart.length;
    cartPayableAmount = 0;

    ngOnInit() {
        this.computeTotal();
    }

    TestingFunction(){
        console.log("Got here");
    }
}

Now I want to access the TestingFunction in my app.component in other class as shown below:

export class BuyTestComponent {

    constructor(private _testService: TestService) {
    }

    public pageTitle: string = "ALL PRACTICE TEST SERIES";

    TestHere() {
        // should call TestingFunction() here.....
    }
}

How to do that? Please help

If you need access to a function from several places, consider putting it in a service as @tibbus mentioned.

utility.service.ts

@Injectable()
export class UtilityService{

    TestingFunction(){}
}

Next, make sure the service is listed in the providers array of your main module:

app.module.ts

// https://angular.io/docs/ts/latest/guide/ngmodule.html#!#ngmodule-properties
@NgModule({ 
  imports:      [ BrowserModule],
  declarations: [ AppComponent, BuyTestComponent ],
  providers:    [ UtilityService ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

You can then inject that service in any component that needs access to the function

buy-test.component.ts

@Component(...)
export class BuyTestComponent {

    //inject service into the component
    constructor(private util:UtilityService){}

    TestHere() {
        //access service function
        this.util.TestingFunction();
    }
}

Angular2 has 2 ways to communicate between 2 components :

  1. Via @Input / @Output if the components have Parent-Child relationship
  2. Via a Service

Both ways are detailed in this article from Angular2 docs : https://angular.io/docs/ts/latest/cookbook/component-communication.html

Assuming your class AppCompenent is saved as app.component.ts Then in your BuyTestComponent class, you need to first import it AppComponent like below

import {AppComponent} from '../app.component';

Assuming both files are saved in the same folder.

Instantiate it in your constructor like below

constructor(public myapp: AppComponent){}

then call it in your BuyTestComponent like below

this.myapp.testingFunction();

lastly, you need to register it as a provider in your app.module.ts

providers: [
 AppComponent,
]

In most of the cases BeetleJuice's answer is the right solution: put the cross-component functionality into service(s).

However sometimes you have unequivocally cohesive components, which you want to connect in the parent component's HTML template.

In this case, using a service would be overhead. Luckily you can use the template reference variables (#var)

Let's say you have a popup component:

// import...

@Component({
    selector: 'my-popup',
    template: '<div *ngIf="visible"><ng-content></ng-content></div>'
})
export class MyPopupComponent {
    public visible: boolean = false;
    public toggle() {
        this.visible = !this.visible;
    }
}

And a toggle component that can trigger a popup component to toggle:

// import...

@Component({
    selector: 'my-popup-toggle',
    template: '<button (click)="popup?.toggle()"><ng-content></ng-content></button>'
})
export class MyPopupToggleComponent {
    @Input('for') popup: MyPopupComponent;
}

Then it's so easy to connect components across the HTML:

<div>
    <my-popup #popup1>Good popup</my-popup>
    <my-popup #popup2>Better popup</my-popup>
    <my-popup #popup3>Best popup</my-popup>
</div>
<div>
    <my-popup-toggle [for]="popup1">Toggle the good</my-popup-toggle>
    <my-popup-toggle [for]="popup2">Toggle the better</my-popup-toggle>
    <my-popup-toggle [for]="popup3">Toggle the best</my-popup-toggle>
    <my-popup-toggle [for]="popup3">Toggle the best with another button</my-popup-toggle>
</div>

In very simple situations you can do something like this too:

<div>
    <my-popup #popup4>Best popup II</my-popup>
</div>
<div>
    <button (click)="popup4.show()">Toggle the best II</button>
</div>

In case you need, you can also access the template reference variable from the parent component:

// import...

@Component({
    selector: 'my-parent-comonent',
    template: `
        ...<my-popup #popup5>Best popup III</my-popup>...
        ...<my-popup #popup6>Best popup IV</my-popup>...
    `
})
export class MyParentComponent {
     @ViewChild('popup5') popup5: MyPopupComponent;
     @ViewChild('popup5') popup5: MyPopupComponent;
     showPopup5() { this.popup5.show(); }
     showPopup6() { this.popup6.show(); }
}

I think the simplest way to achieve this is, basically create a static property in the app component that is populated when onInit

In app.component


export class AppComponent implements OnInit {
  static myapp;

 ngOnInit() {
    AppComponent.myapp = this;
 }
}

then in your component

import { AppComponent } from '../../app.component';
export class UsersComponent  implements OnInit {

 ngOnInit() {
    console.log(AppComponent.myapp);
 }
}

You can use Events like:

app.component.ts

import { Events } from 'ionic-angular';
  constructor(public events: Events) {
    events.subscribe('myEvent', () => {
      this.myMethod();
    });
  }

  myMethod() {
    console.log("my method was activated");
  }

anotherclass

import { Events } from 'ionic-angular';
constructor(public events: Events) {
}

callEvent() {
  this.events.publish('myEvent');
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM