视图完全加载后如何从另一个组件调用方法(AppComponent)? [英] How to call a method from another component after view is fully loaded (AppComponent)?

查看:20
本文介绍了视图完全加载后如何从另一个组件调用方法(AppComponent)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 HeaderComponent 中使用来自 Angular Material 的 MatMenu.我只需要在特定条件(方法)下打开Menu,在ProductDetailComponent上调用这个方法.但是,此方法仅在 ngAfterViewInit() 内有效,在视图加载后.

我找到了一种从 ProductDetailComponentHeaderComponent 进行通信的方法,但是存在访问组件的 Children-Parent 关系.HeaderComponent 是从 AppComponent 调用的.

这里是 AppComponent

<my-header [openMenu]="clickBehavior"></my-header><路由器插座></路由器插座><!-- ProductComponent -->

产品组件

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

ProductDetail 组件

导出类 ProductComponent {clickBehavior = new BehaviorSubject(null);点击() {this.clickBehavior.next(1);}}

ProductDetail 标记

<!-- 我需要把它移到应用组件<my-header [openMenu]="clickBehavior"></my-header>--><div><button (click)="click()">点击</button>

标题组件

导出类HeaderComponent实现AfterViewInit {@ViewChild('trigger') 触发器:MatMenuTrigger;@Input() openMenu: Observable;ngAfterViewInit() {this.openMenu.subscribe(value => {如果(值){this.trigger.openMenu();}});}}

标题标记

解决方案

您可以通过使用共享服务并在需要的地方注入服务来实现这一点.

设置一个共享服务,我使用了获取、设置和切换菜单状态的方法.

SharedService.ts

import { Injectable } from '@angular/core';@Injectable()导出类 SharedService {//当前菜单状态私人 showMenu_ = false;//获取当前菜单状态得到 showMenu() {返回 showMenu_;}//设置菜单状态设置 showMenu(state: boolean) {this.showMenu_ = 状态;}//切换菜单公共切换菜单(){this.showMenu_ = !this.showMenu;}}

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

appComponent.ts

import { SharedService } from 'PATH TO SHARED SERVICE';...构造函数(公共共享服务:共享服务){}

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

appComponent.html

将服务注入任何其他组件/页面以更改菜单的状态.在本例中为 ProductComponent.ts.

ProductComponent.ts

import { SharedService } from 'PATH TO SHARED SERVICE';...构造函数(公共共享服务:共享服务){}

ProductComponent.html

<button (click)="sharedService.toggleMenu()">点击</button>

或者使用来自服务的 BehavourSubject.

在 SharedService 中创建 BehaviorSubject.

import { Injectable } from '@angular/core';@Injectable()导出类 SharedService {//当前菜单状态私人 showMenu_ = false;private showMenu$: BehaviorSubject= 新行为主题(假);//获取对订阅的 showMenu$ 的引用公共菜单状态(){返回 showMenu$;}//更改菜单状态以显示.公共 showMenu(){this.showMenu_ = true;this.showMenu$.next(this.showMenu_);}//将菜单状态更改为隐藏.公共隐藏菜单(){this.showMenu_ = false;this.showMenu$.next(this.showMenu_);}//切换菜单状态.公共切换菜单(){this.showMenu_ = !this.showMenu;this.ShowMenu$.next(this.showMenu_);}//获取当前菜单状态.公共 getMenuState() {返回 this.showMenu$.getValue();}

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

appComponent.ts

import { SharedService } from 'PATH TO SHARED SERVICE';...导出类 appComponent 实现 OnInit, OnDestroy {//用于显示/隐藏菜单的变量.公开表演菜单;//引用订阅,以便我们稍后取消订阅.私有 this.menuStateSub:订阅;构造函数(公共共享服务:共享服务){}ngOnInit() {//订阅menuState BehaviorSubjectthis.menuStateSub = this.sharedService.menuState().subscribe((state)=>{this.showMenu = 状态;})}ngOnDestroy() {//离开页面前取消订阅this.menuStateSub.unsubscribe();}

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

appComponent.html

最后在需要控制菜单状态的地方注入服务.

ProductComponent.ts

import { SharedService } from 'PATH TO SHARED SERVICE';...构造函数(公共共享服务:共享服务){}

现在我们可以使用该服务来切换状态.产品组件.html

<button (click)="sharedService.toggleMenu()">点击</button>

I'm using MatMenu from Angular Material inside HeaderComponent. I just need to open the Menu under certain conditions (method), calling this method on ProductDetailComponent. However this method only works inside ngAfterViewInit(), after the view is loaded.

I found a way to comunicate from ProductDetailComponent to HeaderComponent, however there is a Children-Parent relationship to reach the components. HeaderComponent is called from AppComponent.

Here is AppComponent

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

ProductComponent

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

ProductDetail component

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

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

ProductDetail markup

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

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

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

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

...

constructor(public sharedService: SharedService){}

ProductComponent.html

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

Or with BehavourSubject from service.

Create the BehaviorSubject in SharedService.

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

appComponent.html

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

Finally inject the service where we need to control the menu state.

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

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

这篇关于视图完全加载后如何从另一个组件调用方法(AppComponent)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆