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

时间:2018-08-09 01:51:14

标签: angular typescript angular-material

我在“ Header Component”中使用了来自Angular Material的MatMenu。我只需要在特定条件下打开菜单即可。但是,此方法仅在加载视图后才能在ngAfterViewInit()内部使用。

export class HeaderComponent implements AfterViewInit {
  @ViewChild('triggerCart') trigger: MatMenuTrigger;

  ngAfterViewInit() {
    this.openMenu();
  }

  openMenu() {
    this.trigger.openMenu();
  }
}
<button mat-button 
        [matMenuTriggerFor]="shoppingCartMenu" 
        #triggerCart="matMenuTrigger" 
        (menuOpened)="isOpened($event)" 
        (mouseenter)="largeScreen ? triggerCart.openMenu() : ''">
</button>

我需要从其他组件调用此方法,但是ngAfterViewInit之外的Menu触发器未定义。

<button mat-stroked-button
        (click)="someMethod()">
</button>

export class ProductDetailComponent {
  @ViewChild(HeaderComponent) header: HeaderComponent;
  
  someMethod() {
    this.header.openMenu();
  }
}

在加载了Header Component之后如何实现组件之间的通信?

2 个答案:

答案 0 :(得分:1)

这是一种实现方法的示例(但不一定是最佳方法)。是要提供组件之间交互的概念。

StackBlitz

产品组件

export class ProductComponent {
  clickBehavior = new BehaviorSubject(null);

  click() {
    this.clickBehavior.next(1);
  }
}

产品标记

<my-header [openMenu]="clickBehavior"></my-header>
<div>
  <button (click)="click()">Click</button>
</div>

标题组件

export class HeaderComponent implements AfterViewInit {
  @ViewChild('trigger') trigger: MatMenuTrigger;
  @Input() openMenu: Observable<any>;

  ngAfterViewInit() {
    this.openMenu.subscribe(value => {
      if (value) {
        this.trigger.openMenu();
      }
    });
  }
}

标题标记

<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>

这个想法是触发Header组件的输入,这是通过使用Product组件中的BehaviorSubject来完成的。

参考:

答案 1 :(得分:0)

您可以通过使用共享服务并将其注入到需要的位置来实现此目的。

设置共享服务,我放置获取,设置和切换菜单状态的方法。

注意:为了对此进行动画处理,因为它使用ngIf,您将需要使用角度动画。

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;
    }


}

将服务注入appComponent,以便我们可以使用它控制菜单状态。

appComponent.ts

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

...

constructor(public sharedService: SharedService){}

根据sharedService中设置的状态将my-header设置为显示/隐藏。

appComponent.html

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

将服务注入到其他任何组件/页面中,以更改菜单的状态。 在这种情况下为ProductComponent.ts。

ProductComponent.ts

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

...

constructor(public sharedService: SharedService){}

ProductComponent.html

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

或与BehavourSubject一起使用。

在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();
}

将服务注入到appComponent中,以便我们可以订阅菜单状态。

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();
}

根据sharedService中设置的状态将my-header设置为显示/隐藏。

appComponent.html

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

最后将服务注入到我们需要控制菜单状态的位置。

ProductComponent.ts

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

...

constructor(public sharedService: SharedService){}

,现在我们可以使用该服务来切换状态。 ProductComponent.html

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