Skip to content

Commit

Permalink
feat(module:menu): add nzTriggerSubMenuAction to support click trig…
Browse files Browse the repository at this point in the history
…ger for submenu (#8461)
  • Loading branch information
ParsaArvanehPA authored Nov 22, 2024
1 parent b9c511d commit 860df87
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 25 deletions.
6 changes: 6 additions & 0 deletions components/menu/demo/horizontal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ import { NzMenuModule } from 'ng-zorro-antd/menu';
<li nz-menu-item>Option 6</li>
</ul>
</li>
<li nz-submenu nzTitle="Click me" [nzTriggerSubMenuAction]="'click'">
<ul>
<li nz-menu-item nzDisabled>Option 5</li>
<li nz-menu-item>Option 6</li>
</ul>
</li>
<li nz-submenu nzDisabled nzTitle="Disabled Sub Menu">
<ul>
<li nz-menu-item>Option 5</li>
Expand Down
19 changes: 10 additions & 9 deletions components/menu/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,16 @@ You can set the title of `[nz-submenu]` in the following ways.
<ng-template #titleTpl><span nz-icon nzType="appstore"></span><span>SubTitle</span></ng-template>
```

| Param | Description | Type | Default value |
| ------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------- | -------------- |
| `[nzPlacement]` | placement of pop menu | `'bottomLeft' \| 'bottomCenter' \| 'bottomRight' \| 'topLeft' \| 'topCenter' \| 'topRight'` | `'bottomLeft'` |
| `[nzOpen]` | whether sub menu is open or not, double binding | `boolean` | `false` |
| `[nzDisabled]` | whether sub menu is disabled or not | `boolean` | `false` |
| `[nzTitle]` | set submenu title | `string \| TemplateRef<void>` | - |
| `[nzIcon]` | `icon` type in title | `string` | - |
| `[nzMenuClassName]` | Custom the submenu container's class name | `string` | - |
| `(nzOpenChange)` | nzOpen callback | `EventEmitter<boolean>` | - |
| Param | Description | Type | Default value |
| -------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------- | -------------- |
| `[nzPlacement]` | placement of pop menu | `'bottomLeft' \| 'bottomCenter' \| 'bottomRight' \| 'topLeft' \| 'topCenter' \| 'topRight'` | `'bottomLeft'` |
| `[nzOpen]` | whether sub menu is open or not, double binding | `boolean` | `false` |
| `[nzDisabled]` | whether sub menu is disabled or not | `boolean` | `false` |
| `[nzTitle]` | set submenu title | `string \| TemplateRef<void>` | - |
| `[nzIcon]` | `icon` type in title | `string` | - |
| `[nzMenuClassName]` | Custom the submenu container's class name | `string` | - |
| `[nzTriggerSubMenuAction]` | Which action can trigger submenu open/close | `'hover' \| 'click'` | `'hover'` |
| `(nzOpenChange)` | nzOpen callback | `EventEmitter<boolean>` | - |

### [nz-menu-group]:standalone

Expand Down
19 changes: 10 additions & 9 deletions components/menu/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,16 @@ import { NzMenuModule } from 'ng-zorro-antd/menu';
<ng-template #titleTpl><span nz-icon nzType="appstore"></span><span>SubTitle</span></ng-template>
```

| 参数 | 说明 | 类型 | 默认值 |
| ------------------- | -------------------- | ------------------------------------------------------------------------------------------- | -------------- |
| `[nzPlacement]` | 菜单弹出位置 | `'bottomLeft' \| 'bottomCenter' \| 'bottomRight' \| 'topLeft' \| 'topCenter' \| 'topRight'` | `'bottomLeft'` |
| `[nzOpen]` | 是否展开,可双向绑定 | `boolean` | `false` |
| `[nzDisabled]` | 是否禁用 | `boolean` | `false` |
| `[nzTitle]` | 标题内容 | `string \| TemplateRef<void>` | - |
| `[nzIcon]` | 标题中 `icon` 类型 | `string` | - |
| `[nzMenuClassName]` | 自定义子菜单容器类名 | `string` | - |
| `(nzOpenChange)` | 展开回调 | `EventEmitter<boolean>` | - |
| 参数 | 说明 | 类型 | 默认值 |
| -------------------------- | --------------------------- | ------------------------------------------------------------------------------------------- | -------------- |
| `[nzPlacement]` | 菜单弹出位置 | `'bottomLeft' \| 'bottomCenter' \| 'bottomRight' \| 'topLeft' \| 'topCenter' \| 'topRight'` | `'bottomLeft'` |
| `[nzOpen]` | 是否展开,可双向绑定 | `boolean` | `false` |
| `[nzDisabled]` | 是否禁用 | `boolean` | `false` |
| `[nzTitle]` | 标题内容 | `string \| TemplateRef<void>` | - |
| `[nzIcon]` | 标题中 `icon` 类型 | `string` | - |
| `[nzMenuClassName]` | 自定义子菜单容器类名 | `string` | - |
| `[nzTriggerSubMenuAction]` | SubMenu 展开/关闭的触发行为 | `'hover' \| 'click'` | `'hover'` |
| `(nzOpenChange)` | 展开回调 | `EventEmitter<boolean>` | - |

### [nz-menu-group]:standalone

Expand Down
46 changes: 45 additions & 1 deletion components/menu/menu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { NzButtonModule } from 'ng-zorro-antd/button';
import { dispatchFakeEvent } from 'ng-zorro-antd/core/testing';
import { NzIconModule } from 'ng-zorro-antd/icon';
import { provideNzIconsTesting } from 'ng-zorro-antd/icon/testing';
import { NzSubmenuTrigger } from 'ng-zorro-antd/menu/menu.types';

import { NzMenuItemComponent } from './menu-item.component';
import { NzMenuDirective } from './menu.directive';
Expand Down Expand Up @@ -271,6 +272,42 @@ describe('menu', () => {
expect(mouseenterCallback).toHaveBeenCalledWith(true);
expect(mouseenterCallback).toHaveBeenCalledTimes(1);
});
it('should have "hover" as default trigger', () => {
fixture.detectChanges();
const mouseenterCallback = jasmine.createSpy('mouseenter callback');
const subs = testComponent.subs.toArray();
const title = submenu.nativeElement.querySelector('.ant-menu-submenu-title');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(subs[0].nzSubmenuService as any).isMouseEnterTitleOrOverlay$.subscribe(mouseenterCallback);
dispatchFakeEvent(title, 'mouseenter');
fixture.detectChanges();
expect(mouseenterCallback).toHaveBeenCalledWith(true);
expect(mouseenterCallback).toHaveBeenCalledTimes(1);
});
it('should have not open with mouse hover if trigger is set to "click"', () => {
testComponent.nzTriggerSubMenuAction = 'click';
fixture.detectChanges();
const mouseenterCallback = jasmine.createSpy('mouseenter callback');
const subs = testComponent.subs.toArray();
const title = submenu.nativeElement.querySelector('.ant-menu-submenu-title');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(subs[0].nzSubmenuService as any).isMouseEnterTitleOrOverlay$.subscribe(mouseenterCallback);
dispatchFakeEvent(title, 'mouseenter');
fixture.detectChanges();
expect(mouseenterCallback).toHaveBeenCalledTimes(0);
});
it('should open with mouse click if trigger is set to "click"', () => {
testComponent.nzTriggerSubMenuAction = 'click';
fixture.detectChanges();
const mouseenterCallback = jasmine.createSpy('mouseenter callback');
const subs = testComponent.subs.toArray();
const title = submenu.nativeElement.querySelector('.ant-menu-submenu-title');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(subs[0].nzSubmenuService as any).isMouseEnterTitleOrOverlay$.subscribe(mouseenterCallback);
title.click();
fixture.detectChanges();
expect(mouseenterCallback).toHaveBeenCalledTimes(1);
});
it('should submenu mouseleave work', () => {
fixture.detectChanges();
const mouseleaveCallback = jasmine.createSpy('mouseleave callback');
Expand Down Expand Up @@ -524,7 +561,13 @@ describe('menu', () => {
imports: [NzIconModule, NzMenuModule],
template: `
<ul nz-menu [nzMode]="'horizontal'">
<li nz-submenu nzMenuClassName="submenu" [nzOpen]="open" [style.width.px]="width">
<li
nz-submenu
[nzTriggerSubMenuAction]="nzTriggerSubMenuAction"
nzMenuClassName="submenu"
[nzOpen]="open"
[style.width.px]="width"
>
<span title>
<span nz-icon nzType="setting"></span>
Navigation Three - Submenu
Expand Down Expand Up @@ -567,6 +610,7 @@ export class NzTestMenuHorizontalComponent {
width = 200;
open = false;
disabled = false;
nzTriggerSubMenuAction: NzSubmenuTrigger = 'hover';
@ViewChildren(NzSubMenuComponent) subs!: QueryList<NzSubMenuComponent>;
@ViewChild('menuitem', { static: false, read: ElementRef }) menuitem!: ElementRef;
@ViewChild('menuitem1', { static: false, read: ElementRef }) menuitem1!: ElementRef;
Expand Down
1 change: 1 addition & 0 deletions components/menu/menu.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@

export type NzMenuModeType = 'vertical' | 'horizontal' | 'inline';
export type NzMenuThemeType = 'light' | 'dark';
export type NzSubmenuTrigger = 'hover' | 'click';
5 changes: 3 additions & 2 deletions components/menu/submenu-non-inline-child.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { takeUntil } from 'rxjs/operators';
import { slideMotion, zoomBigMotion } from 'ng-zorro-antd/core/animation';
import { NzSafeAny } from 'ng-zorro-antd/core/types';

import { NzMenuModeType, NzMenuThemeType } from './menu.types';
import { NzMenuModeType, NzMenuThemeType, NzSubmenuTrigger } from './menu.types';

@Component({
selector: '[nz-submenu-none-inline-child]',
Expand Down Expand Up @@ -68,6 +68,7 @@ export class NzSubmenuNoneInlineChildComponent implements OnDestroy, OnInit, OnC
@Input() templateOutlet: TemplateRef<NzSafeAny> | null = null;
@Input() isMenuInsideDropDown = false;
@Input() mode: NzMenuModeType = 'vertical';
@Input() nzTriggerSubMenuAction: NzSubmenuTrigger = 'hover';
@Input() position = 'right';
@Input() nzDisabled = false;
@Input() nzOpen = false;
Expand All @@ -76,7 +77,7 @@ export class NzSubmenuNoneInlineChildComponent implements OnDestroy, OnInit, OnC
constructor(private directionality: Directionality) {}

setMouseState(state: boolean): void {
if (!this.nzDisabled) {
if (!this.nzDisabled && this.nzTriggerSubMenuAction === 'hover') {
this.subMenuMouseState.next(state);
}
}
Expand Down
8 changes: 5 additions & 3 deletions components/menu/submenu-title.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { takeUntil } from 'rxjs/operators';
import { NzOutletModule } from 'ng-zorro-antd/core/outlet';
import { NzIconModule } from 'ng-zorro-antd/icon';

import { NzMenuModeType } from './menu.types';
import { NzMenuModeType, NzSubmenuTrigger } from './menu.types';

@Component({
selector: '[nz-submenu-title]',
Expand Down Expand Up @@ -71,6 +71,7 @@ export class NzSubMenuTitleComponent implements OnDestroy, OnInit {
@Input() nzDisabled = false;
@Input() paddingLeft: number | null = null;
@Input() mode: NzMenuModeType = 'vertical';
@Input() nzTriggerSubMenuAction: NzSubmenuTrigger = 'hover';
@Output() readonly toggleSubMenu = new EventEmitter();
@Output() readonly subMenuMouseState = new EventEmitter<boolean>();

Expand All @@ -95,12 +96,13 @@ export class NzSubMenuTitleComponent implements OnDestroy, OnInit {
}

setMouseState(state: boolean): void {
if (!this.nzDisabled) {
if (!this.nzDisabled && this.nzTriggerSubMenuAction === 'hover') {
this.subMenuMouseState.next(state);
}
}
clickTitle(): void {
if (this.mode === 'inline' && !this.nzDisabled) {
if ((this.mode === 'inline' || this.nzTriggerSubMenuAction === 'click') && !this.nzDisabled) {
this.subMenuMouseState.next(true);
this.toggleSubMenu.emit();
}
}
Expand Down
6 changes: 5 additions & 1 deletion components/menu/submenu.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { getPlacementName, POSITION_MAP, POSITION_TYPE_HORIZONTAL } from 'ng-zor
import { NzMenuItemComponent } from './menu-item.component';
import { MenuService } from './menu.service';
import { NzIsMenuInsideDropDownToken } from './menu.token';
import { NzMenuModeType, NzMenuThemeType } from './menu.types';
import { NzMenuModeType, NzMenuThemeType, NzSubmenuTrigger } from './menu.types';
import { NzSubmenuInlineChildComponent } from './submenu-inline-child.component';
import { NzSubmenuNoneInlineChildComponent } from './submenu-non-inline-child.component';
import { NzSubMenuTitleComponent } from './submenu-title.component';
Expand Down Expand Up @@ -76,6 +76,7 @@ const listOfHorizontalPositions = [
[nzDisabled]="nzDisabled"
[isMenuInsideDropDown]="isMenuInsideDropDown"
[paddingLeft]="nzPaddingLeft || inlinePaddingLeft"
[nzTriggerSubMenuAction]="nzTriggerSubMenuAction"
(subMenuMouseState)="setMouseEnterState($event)"
(toggleSubMenu)="toggleSubMenu()"
>
Expand All @@ -102,6 +103,7 @@ const listOfHorizontalPositions = [
[cdkConnectedOverlayWidth]="triggerWidth!"
[cdkConnectedOverlayOpen]="nzOpen"
[cdkConnectedOverlayTransformOriginOn]="'.ant-menu-submenu'"
(overlayOutsideClick)="setMouseEnterState(false)"
>
<div
nz-submenu-none-inline-child
Expand All @@ -111,6 +113,7 @@ const listOfHorizontalPositions = [
[position]="position"
[nzDisabled]="nzDisabled"
[isMenuInsideDropDown]="isMenuInsideDropDown"
[nzTriggerSubMenuAction]="nzTriggerSubMenuAction"
[templateOutlet]="subMenuTemplate"
[menuClass]="nzMenuClassName"
[@.disabled]="!!noAnimation?.nzNoAnimation"
Expand Down Expand Up @@ -157,6 +160,7 @@ export class NzSubMenuComponent implements OnInit, OnDestroy, AfterContentInit,
@Input() nzPaddingLeft: number | null = null;
@Input() nzTitle: string | TemplateRef<void> | null = null;
@Input() nzIcon: string | null = null;
@Input() nzTriggerSubMenuAction: NzSubmenuTrigger = 'hover';
@Input({ transform: booleanAttribute }) nzOpen = false;
@Input({ transform: booleanAttribute }) nzDisabled = false;
@Input() nzPlacement: POSITION_TYPE_HORIZONTAL = 'bottomLeft';
Expand Down

0 comments on commit 860df87

Please sign in to comment.