diff --git a/components/core/overlay/overlay-position.ts b/components/core/overlay/overlay-position.ts
index c06ea6f449..6a67276c16 100644
--- a/components/core/overlay/overlay-position.ts
+++ b/components/core/overlay/overlay-position.ts
@@ -37,6 +37,10 @@ export const POSITION_MAP = {
)
};
export type POSITION_TYPE = keyof typeof POSITION_MAP;
+export type POSITION_TYPE_HORIZONTAL = Extract<
+ POSITION_TYPE,
+ 'bottomLeft' | 'bottomCenter' | 'bottomRight' | 'topLeft' | 'topCenter' | 'topRight'
+>;
export const DEFAULT_TOOLTIP_POSITIONS = [POSITION_MAP.top, POSITION_MAP.right, POSITION_MAP.bottom, POSITION_MAP.left];
diff --git a/components/menu/demo/horizontal-position.md b/components/menu/demo/horizontal-position.md
new file mode 100755
index 0000000000..16fb48c8ee
--- /dev/null
+++ b/components/menu/demo/horizontal-position.md
@@ -0,0 +1,14 @@
+---
+order: 1
+title:
+ zh-CN: 弹出位置
+ en-US: Placement
+---
+
+## zh-CN
+
+支持 6 个弹出位置。
+
+## en-US
+
+Support 6 placements.
\ No newline at end of file
diff --git a/components/menu/demo/horizontal-position.ts b/components/menu/demo/horizontal-position.ts
new file mode 100755
index 0000000000..3630db2867
--- /dev/null
+++ b/components/menu/demo/horizontal-position.ts
@@ -0,0 +1,178 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'nz-demo-menu-horizontal-position',
+ template: `
+
+ -
+
+ -
+
+
+ -
+
+ - Option 3
+ - Option 4
+ -
+
+
+ -
+
+
+
+
+
+
+ -
+
+ -
+
+
+ -
+
+ - Option 3
+ - Option 4
+ -
+
+
+ -
+
+
+
+
+
+
+ -
+
+ -
+
+
+ -
+
+ - Option 3
+ - Option 4
+ -
+
+
+ -
+
+
+
+
+
+
+ -
+
+ -
+
+
+ -
+
+ - Option 3
+ - Option 4
+ -
+
+
+ -
+
+
+
+
+
+
+ -
+
+ -
+
+
+ -
+
+ - Option 3
+ - Option 4
+ -
+
+
+ -
+
+
+
+
+
+
+ -
+
+ -
+
+
+ -
+
+ - Option 3
+ - Option 4
+ -
+
+
+ -
+
+
+
+
+
+
+
+ `
+})
+export class NzDemoMenuHorizontalPositionComponent {}
diff --git a/components/menu/doc/index.en-US.md b/components/menu/doc/index.en-US.md
index 90d8f8a78b..3bc924167c 100755
--- a/components/menu/doc/index.en-US.md
+++ b/components/menu/doc/index.en-US.md
@@ -70,6 +70,7 @@ You can set the title of `[nz-submenu]` in the following ways.
| 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` | - |
diff --git a/components/menu/doc/index.zh-CN.md b/components/menu/doc/index.zh-CN.md
index 3f52c72e51..2a3412b8e8 100755
--- a/components/menu/doc/index.zh-CN.md
+++ b/components/menu/doc/index.zh-CN.md
@@ -71,6 +71,7 @@ import { NzMenuModule } from 'ng-zorro-antd/menu';
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
+| `[nzPlacement]` | 菜单弹出位置 | `'bottomLeft' \| 'bottomCenter' \| 'bottomRight' \| 'topLeft' \| 'topCenter' \| 'topRight'` | `'bottomLeft'` |
| `[nzOpen]` | 是否展开,可双向绑定 | `boolean` | `false` |
| `[nzDisabled]` | 是否禁用 | `boolean` | `false` |
| `[nzTitle]` | 标题内容 | `string \| TemplateRef` | - |
diff --git a/components/menu/submenu.component.ts b/components/menu/submenu.component.ts
index aa384b9688..2a0ba8e170 100644
--- a/components/menu/submenu.component.ts
+++ b/components/menu/submenu.component.ts
@@ -32,7 +32,7 @@ import { combineLatest, merge, Subject } from 'rxjs';
import { map, startWith, switchMap, takeUntil } from 'rxjs/operators';
import { NzNoAnimationDirective } from 'ng-zorro-antd/core/no-animation';
-import { getPlacementName, POSITION_MAP } from 'ng-zorro-antd/core/overlay';
+import { getPlacementName, POSITION_MAP, POSITION_TYPE_HORIZONTAL } from 'ng-zorro-antd/core/overlay';
import { BooleanInput } from 'ng-zorro-antd/core/types';
import { InputBoolean } from 'ng-zorro-antd/core/util';
@@ -50,7 +50,12 @@ const listOfVerticalPositions = [
POSITION_MAP.left,
POSITION_MAP.leftBottom
];
-const listOfHorizontalPositions = [POSITION_MAP.bottomLeft];
+const listOfHorizontalPositions = [
+ POSITION_MAP.bottomLeft,
+ POSITION_MAP.bottomRight,
+ POSITION_MAP.topRight,
+ POSITION_MAP.topLeft
+];
@Component({
selector: '[nz-submenu]',
@@ -146,6 +151,7 @@ export class NzSubMenuComponent implements OnInit, OnDestroy, AfterContentInit,
@Input() nzIcon: string | null = null;
@Input() @InputBoolean() nzOpen = false;
@Input() @InputBoolean() nzDisabled = false;
+ @Input() nzPlacement: POSITION_TYPE_HORIZONTAL = 'bottomLeft';
@Output() readonly nzOpenChange: EventEmitter = new EventEmitter();
@ViewChild(CdkOverlayOrigin, { static: true, read: ElementRef }) cdkOverlayOrigin: ElementRef | null = null;
@ContentChildren(NzSubMenuComponent, { descendants: true })
@@ -181,7 +187,12 @@ export class NzSubMenuComponent implements OnInit, OnDestroy, AfterContentInit,
}
setTriggerWidth(): void {
- if (this.mode === 'horizontal' && this.platform.isBrowser && this.cdkOverlayOrigin) {
+ if (
+ this.mode === 'horizontal' &&
+ this.platform.isBrowser &&
+ this.cdkOverlayOrigin &&
+ this.nzPlacement === 'bottomLeft'
+ ) {
/** TODO: fast dom **/
this.triggerWidth = this.cdkOverlayOrigin!.nativeElement.getBoundingClientRect().width;
}
@@ -216,7 +227,7 @@ export class NzSubMenuComponent implements OnInit, OnDestroy, AfterContentInit,
this.nzSubmenuService.mode$.pipe(takeUntil(this.destroy$)).subscribe(mode => {
this.mode = mode;
if (mode === 'horizontal') {
- this.overlayPositions = listOfHorizontalPositions;
+ this.overlayPositions = [POSITION_MAP[this.nzPlacement], ...listOfHorizontalPositions];
} else if (mode === 'vertical') {
this.overlayPositions = listOfVerticalPositions;
}