简体   繁体   English

完全加载视图(AppComponent)后如何从另一个组件调用方法?

[英]How to call a method from another component after view is fully loaded (AppComponent)?

I'm using MatMenu from Angular Material inside HeaderComponent . 我正在HeaderComponent内的Angular Material中使用MatMenu。 I just need to open the Menu under certain conditions (method), calling this method on ProductDetailComponent . 我只需要在某些条件(方法)下打开菜单,然后在ProductDetailComponent上调用此方法即可。 However this method only works inside ngAfterViewInit() , after the view is loaded. 但是,此方法仅在加载视图之后在ngAfterViewInit()内部ngAfterViewInit()

I found a way to comunicate from ProductDetailComponent to HeaderComponent , however there is a Children-Parent relationship to reach the components. 我找到了一种从ProductDetailComponentHeaderComponent进行通信的方法,但是有一个Children-Parent关系可以到达这些组件。 HeaderComponent is called from AppComponent . HeaderComponentAppComponent

Here is AppComponent 这是AppComponent

 <my-header [openMenu]="clickBehavior"></my-header> <router-outlet></router-outlet> <!-- ProductComponent --> 

ProductComponent ProductComponent

 <router-outlet></router-outlet> <!-- ProductDetailComponent --> 

ProductDetail component ProductDetail组件

 export class ProductComponent { clickBehavior = new BehaviorSubject(null); click() { this.clickBehavior.next(1); } } 

ProductDetail markup ProductDetail标记

 <!-- i need to move it to app component <my-header [openMenu]="clickBehavior"></my-header> --> <div> <button (click)="click()">Click</button> </div> 

Header component 标头组件

 export class HeaderComponent implements AfterViewInit { @ViewChild('trigger') trigger: MatMenuTrigger; @Input() openMenu: Observable<any>; ngAfterViewInit() { this.openMenu.subscribe(value => { if (value) { this.trigger.openMenu(); } }); } } 

Header markup 标头标记

 <button mat-button [matMenuTriggerFor]="menu" #trigger="matMenuTrigger">Menu </button> <mat-menu #menu="matMenu"> <button mat-menu-item>Item 1</button> <button mat-menu-item>Item 2</button> </mat-menu> 

You can achieve this by using a shared service and injecting the service where it is required. 您可以通过使用共享服务并在需要的地方注入服务来实现。

Setup a shared service, i put methods to get, set and toggle the menu state. 设置共享服务,我将方法设置为获取,设置和切换菜单状态。

SharedService.ts SharedService.ts

import { Injectable } from '@angular/core';

    @Injectable()
    export class SharedService {

    //The current menu state
    private showMenu_ = false;

    //get the current menu state
    get showMenu() {
        return showMenu_;
    }

    //set the menu state
    set showMenu(state: boolean) {
        this.showMenu_ = state;
    }

    //toggle the menu
    public toggleMenu() {
        this.showMenu_ = !this.showMenu;
    }


}

Inject the service into appComponent so we can control the menu state with it. 将服务注入到appComponent中,以便我们可以使用它控制菜单状态。

appComponent.ts appComponent.ts

import { SharedService } from 'PATH TO SHARED SERVICE';

...

constructor(public sharedService: SharedService){}

Set my-header to show/hide based on the state set in the sharedService. 根据sharedService中设置的状态将my-header设置为显示/隐藏。

appComponent.html appComponent.html

<my-header *ngIf="sharedService.showMenu"></my-header>

Inject the service into any other component/page to change the state of the menu. 将服务注入任何其他组件/页面以更改菜单的状态。 In this case ProductComponent.ts. 在这种情况下为ProductComponent.ts。

ProductComponent.ts ProductComponent.ts

import { SharedService } from 'PATH TO SHARED SERVICE';

...

constructor(public sharedService: SharedService){}

ProductComponent.html ProductComponent.html

<div>
  <button (click)="sharedService.toggleMenu()">Click</button>
</div>

Or with BehavourSubject from service. 或与BehavourSubject脱离服务。

Create the BehaviorSubject in SharedService. 在SharedService中创建BehaviorSubject。

import { Injectable } from '@angular/core';

@Injectable()
export class SharedService {

//The current menu state
private showMenu_ = false;
private showMenu$: BehaviorSubject<boolean> = new 
BehaviorSubject(false);

//get a reference to showMenu$ for subscription
public menuState() {
    return showMenu$;
}

//Change menu state to show.
public showMenu(){
    this.showMenu_ = true;
    this.showMenu$.next(this.showMenu_);
}

//Change menu state to hide.
public hideMenu(){
    this.showMenu_ = false;
    this.showMenu$.next(this.showMenu_);
}

//Toggle menu state.
public toggleMenu(){
    this.showMenu_ = !this.showMenu;
    this.ShowMenu$.next(this.showMenu_);
}

//get the current menu state.
public getMenuState() {
    return this.showMenu$.getValue();
}

Inject the service into appComponent so we can subscribe to the menu state. 将服务注入appComponent,以便我们可以订阅菜单状态。

appComponent.ts appComponent.ts

import { SharedService } from 'PATH TO SHARED SERVICE';

...

export class appComponent implements OnInit, OnDestroy {

//variable used to show/hide the menu.
public showMenu;

//reference to subscription so we can unsubscribe later.
private this.menuStateSub: Subscription;

constructor(public sharedService: SharedService){}

ngOnInit() {  
    //subscribe to the menuState BehaviorSubject
    this.menuStateSub = this.sharedService.menuState().subscribe((state)=>{
        this.showMenu = state;
    })
}

ngOnDestroy() {
    //unsubscribe before leaving the page
    this.menuStateSub.unsubscribe();
}

Set my-header to show/hide based on the state set in the sharedService. 根据sharedService中设置的状态将my-header设置为显示/隐藏。

appComponent.html appComponent.html

<my-header *ngIf="sharedService.showMenu"></my-header>

Finally inject the service where we need to control the menu state. 最后,将服务注入我们需要控制菜单状态的位置。

ProductComponent.ts ProductComponent.ts

import { SharedService } from 'PATH TO SHARED SERVICE';

...

constructor(public sharedService: SharedService){}

and now we can use the service to toggle the state. 现在我们可以使用该服务来切换状态。 ProductComponent.html ProductComponent.html

<div>
  <button (click)="sharedService.toggleMenu()">Click</button>
</div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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