角材料-无法使多个项目工作 [英] Angular Materials - can't get multi items to work

查看:51
本文介绍了角材料-无法使多个项目工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将Angular 8与Angular Materials一起使用来构建多级菜单.我可以通过对每个级别使用递归来使菜单起作用.我递归地调用显示菜单的每个级别的同一指令.

I am using Angular 8 with Angular Materials to build a multi-level menu. I can get the menu to work by using recursion for each level. I recursively call the same directive that displays each level of the menu.

这一切正常,并且菜单按预期构建.但是,菜单的行为不符合预期.我看到的示例是,当您将鼠标悬停在某个项目上时,嵌套项目就会打开,而如果您移开某个项目,则其子项目也会关闭.

This all works, and the menu is built as expected. However, the menu does not behave as expected. Examples I have seen, when you hover over an item, the nest item is opened, and if you move off an item, its child is closed.

例如,这是我制作的一个简单版本:

For example, this is a simple version I made:

https://stackblitz.com/edit/dynamic-sidenav-multi-level-menu-tvim5b?file=app/app.component.html

问题

我的问题是建立菜单时,如果单击某个项目,则该子项将打开.但是,除非完全单击菜单,否则我永远无法让孩子关闭.它的行为不像上面的示例.

My issue is when I build my menu, if I click on an item, the child opens. However, I can never get the child to close unless I click off the menu altogether. It is not behaving like the above example.

问题

如何使我的示例具有上述特征,并在菜单项失去焦点时关闭菜单项(子项)?

How can I get my example to be have like the above, and close menu items (children) when the items loses focus?

信息

我没有将我的特定示例放在StackBlitz中,因为我不拥有代码,并且它需要后端服务来支持实现.

I have not put my specific example in StackBlitz because I don't own the code, and it needs backend services to support the implementation.

我认为我的问题是因为我正在递归地构建菜单项,而[matMenuTriggerFor]在下一次递归中引用了菜单.

I think my issues are because I am building the menu items recursively , and the [matMenuTriggerFor] is referencing the menu in the next recursion.

代码

sidenav-list.component.html

sidenav-list.component.html

<mat-nav-list>
  <!-- Add the Home item -->
  <a mat-list-item routerLink="/home" (click)="onSidenavClose()"><mat-icon>home</mat-icon><span class="nav-caption">Home</span></a>
  <!-- Recurse over the app-sidenav-item -->
  <app-sidenav-item *ngFor="let item of navItems" [item]="item" [depth]="depth+1" [sidenavClose]="sidenavClose"></app-sidenav-item>
</mat-nav-list>

sidenav-item.component.html <app-sidenav-item>

sidenav-item.component.html <app-sidenav-item>

<div>
    <button mat-button *ngIf="depth === 1" [matMenuTriggerFor]="menu"><mat-icon>play_arrow</mat-icon>{{item.name | titlecase}}</button>
    <button mat-menu-item *ngIf="depth > 1" [matMenuTriggerFor]="menu">{{item.name}}</button>

    <mat-menu #menu="matMenu">
        <button *ngIf="item.actions.getItems" mat-menu-item (click)="onItemSelected(item, 0)"><mat-icon>list</mat-icon>Get Items</button>
        <button *ngIf="item.actions.updateItem" mat-menu-item (click)="onItemSelected(item, 1)"><mat-icon>edit</mat-icon>Update Items</button>
        <button *ngIf="item.actions.addItem" mat-menu-item (click)="onItemSelected(item, 2)"><mat-icon>add</mat-icon>Add Item</button>

        <app-sidenav-item *ngFor="let child of item.children" [item]="child" [depth]="depth+1" [sidenavClose]="sidenavClose"></app-sidenav-item>
    </mat-menu>
</div>

屏幕打印

如您所见,我能够在单独的节点上打开多个项目.我无法关闭上一个.此外,它仅响应点击,而不响应鼠标悬停.

As you can see, I am able to open more than one item on separate nodes. I cannot get the previous one to close. Also, it only responds to clicks and not mouse hover.

推荐答案

好,这是事情,您必须对数据进行2种预处理,这意味着您必须在对象中知道是否有子级才能启用更多层次结构级别并且您需要知道它来自哪个父级以对其进行过滤以构建它

Ok here is the thing, You have to preprocess some data 2 way, that means in your object you have to know if it has children to enable more hierarchy level and you need to know which parent it came from to filter it to build this

,您的html应该如下所示.由于您知道可以进入3-4个级别,因此会为这些级别生成模板,并在有数据时播放它们.

and your html should look like this. Since you know you can go 3 - 4 levels you generate template for those levels and play with data when it is there.

MatMenu还有另一个@input输入,称为matMenuTriggerData,父级将使用该输入将数据触发给子级.

There is also another @input for MatMenu called matMenuTriggerData with which the parent will trigger data to child.

<button mat-button [matMenuTriggerFor]="level1" [matMenuTriggerData]="getData(null, 1)">Animal index</button>


<mat-menu #level1="matMenu">
  <ng-template matMenuContent let-data="data">
      <ng-template ngFor let-item [ngForOf]="data">
          <button mat-menu-item *ngIf="item.children" [matMenuTriggerFor]="level2"
            [matMenuTriggerData]="getData(item, 2)">{{item.label}}</button>
          <button mat-menu-item *ngIf="!item.children">{{item.label}}</button>
        </ng-template>
  </ng-template>
</mat-menu>

<mat-menu #level2="matMenu">
  <ng-template matMenuContent let-data="data">
    <ng-template ngFor let-item [ngForOf]="data">
      <button mat-menu-item *ngIf="item.children" [matMenuTriggerFor]="level3"
        [matMenuTriggerData]="getData(item, 3)">{{item.label}}</button>
      <button mat-menu-item *ngIf="!item.children">{{item.label}}</button>
    </ng-template>
  </ng-template>
</mat-menu>

<mat-menu #level3="matMenu">
  <ng-template matMenuContent let-data="data">
    <button mat-menu-item *ngFor="let item of data">{{item.label}}</button>
  </ng-template>
</mat-menu>

请注意最后一级没有更多的触发器.

Note the last level has no more triggers.

您可以为过滤后的数据编写函数

you can write a function for your filtered data

getData(selected, requested) {
  return selected ? {
    data:
      this['level' + requested].filter(item => item.parent === selected.value)
  } : { data: this.level1 };
}

每个项目将包含不同级别的valuelabelparenthasChildren,您可以直接与api挂钩,以确保传递的对象具有data属性,请参阅functon getData

Each item will contain value, label, parent and hasChildren in different levels, you can directly hook up with api make sure the object is passed has a data attribute , see functon getData

您可以在 https://stackblitz.com/edit/angular-yfslub 上签出此解决方案 a>

You can checkout this solution at https://stackblitz.com/edit/angular-yfslub

希望您可以根据需要进行修改.

Hope you can modify to your needs.

这篇关于角材料-无法使多个项目工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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