【问题标题】:mat-menu and button in different components不同组件中的垫子菜单和按钮
【发布时间】:2018-06-28 19:28:46
【问题描述】:

我有

<mat-menu #saveMenu="matMenu">...</mat-menu>

在 app-save-document 组件中和

<app-save-document></app-save-document>
<button mat-icon-button [matMenuTriggerFor]="saveMenu">

在另一个组件中。

如果我在不同的组件中有 mat-menu 和带有 [matMenuTriggerFor] 的按钮,我可以做些什么让按钮看到菜单吗?

现在我有ERROR Error: mat-menu-trigger: must pass in an mat-menu instance.

【问题讨论】:

    标签: angular-cli angular-material2


    【解决方案1】:

    我使用的是@julianobrasil 的第二种方法,但就我而言,我的要求是在单击菜单组件(子组件)中的十字图标时关闭对话框。 所以,用了这个方法...

    <button [matMenuTriggerFor]="menu" [matMenuTriggerData]="{ 'data': 'someData' }">
    
    <mat-menu #menu="matMenu" [hasBackdrop]="false">
      <ng-template matMenuContent let-data="data">
        <child-comp 
          (close)="onCloseMenu()"
          [input-to-child-comp]="data"
        >
        </child-comp>
      </ng-template>
    </mat-menu>
    

    [hasBackdrop]="false"避免在外部点击时关闭菜单。

    我使用 ng-template 将一些数据传递给子菜单组件。

    在子组件中我使用了一个按钮来关闭菜单,

      <mat-icon class="material-icons-outlined" (click)="closeMenu()">close</maticon>
    

    在closeMenu函数中只是发出关闭事件,关闭菜单,

     @Output() close = new EventEmitter();
      closeMenu() {
        this.close.emit();
      }
    

    在父组件中,

      @ViewChild(MatMenuTrigger) menu: MatMenuTrigger;
      onCloseMenu() {
        this.menu.closeMenu();
      }
    

    & 一切正常。

    【讨论】:

      【解决方案2】:

      好吧,如果你想做这样的事情:

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

      您可以像这样编码&lt;other-component&gt;

      import {Component,Input} from '@angular/core';
      import {MatMenu} from '@angular/material';
      
      @Component({
        selector: 'other-component',
        template: `
          This button is in another component:
          <button [matMenuTriggerFor]="matMenu">Click here to open menu</button>
        `,
      })
      export class OtherComponent {
        @Input() matMenu: MatMenu;
      }
      

      你可以在stackblitz demo看到上面的例子。


      另一种方法

      另一种方法是(我认为这是您想要的):您的 触发按钮 在父级内部(但在子级外部menu 本身是在 子组件内 定义的。

      父组件:

      <button mat-button [matMenuTriggerFor]="childComponentMenu?.menu">
          Menu in other component
      </button>
      <child-component></child-component>
      
      export class ParentComponent {
        @ViewChild(ChildComponent) childComponentMenu: ChildComponent;
      }
      

      子组件:

      @Component({
        selector: 'child-component',
        template: `
          <mat-menu>
            <button mat-menu-item>Item 1 (inside other component)</button>
            <button mat-menu-item>Item 2 (inside other component)</button>
          </mat-menu>
        `,
      })
      export class ChildComponent {
        @ViewChild(MatMenu, {static: true}) menu: MatMenu;
      }
      

      另一种方法

      另一种方法,与上面类似,但使用模板引用变量(注意子组件装饰器中的exportAs):

      父组件:

      <button mat-button [matMenuTriggerFor]="x.menu">
          Menu in other component
      </button>
      <child-component #x="menuInOtherComponent"></child-component>
      
      export class ParentComponent {
      }
      

      子组件:

      @Component({
        selector: 'child-component',
        template: `
          <mat-menu>
            <button mat-menu-item>Item 1 (inside other component)</button>
            <button mat-menu-item>Item 2 (inside other component)</button>
          </mat-menu>
        `,
        exportAs: 'menuInOtherComponent',
      })
      export class ChildComponent {
        @ViewChild(MatMenu, {static: true}) menu: MatMenu;
      }
      

      Stackblitz demo

      【讨论】:

      • 谢谢你,正如人们所说,第三个是完美的。我第一次遇到 exportAs 属性!
      • 第三个不需要exportAs。只需使用[matMenuTriggerFor]="x.menu"&lt;child-component #x&gt;
      • @jpavel 我的意思是在我今天必须实现它的子组件中没有&lt;mat-menu&gt;(= 第四种方法)并且它也有效,..
      • @julianobrasil,在 Angular 9 中,默认值已从 {static: true} 更改为 {static: false}。如果没有在 Angular 9 中指定 {static: true},那么这个演示可能会在控制台中出现错误。我没有检查这个演示,但这是我在代码库中看到的。
      • @АнтонДосов,谢谢。我已将演示更新为 angular 9。
      【解决方案3】:

      这是另一个使用ng-content 的解决方案。这是我的首选方式。

      我的自定义菜单组件 html:

      <div [matMenuTriggerFor]="menu">
        <ng-content></ng-content>
      </div>
      
      <mat-menu #menu="matMenu">
        menu content
      </mat-menu>
      

      父组件html:

      <my-custom-menu-component>
        <button>click me</button>
      <my-custom-menu-component>
      

      【讨论】:

      • 那个按钮是怎么挂在菜单上的?
      • 看起来最终产品有一个不可见的div,并带有一个围绕实际按钮的点击处理程序。这对我来说不像是声音设计——matMenuTriggerFor 属性确实应该附加到按钮,而不是 div。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-14
      • 1970-01-01
      • 2021-06-25
      • 2018-06-03
      • 2019-06-04
      • 2020-03-24
      • 1970-01-01
      相关资源
      最近更新 更多