# layout-menus

> angular9.0+ LayoutMenus

Latest version **2.0.2** (published 2020-08-18) · MIT license · 0 weekly downloads

## Install

```sh
npm install layout-menus
pnpm add layout-menus
yarn add layout-menus
bun add layout-menus
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities.

Warnings: low downloads.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 2.0.2 |
| Published | 2020-08-18 |
| First published | 2019-10-22 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 2 |
| Unpacked size | 1.3 MB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 5 |
| Maintainers | iecy |
| Keywords | angular2, angular, ng2, ng, layout-menus |

## Links

- npm: https://www.npmjs.com/package/layout-menus
- Repository: https://github.com/Iecy/ngx-library/tree/master/projects/layout-menus
- Issues: https://github.com/Iecy/ngx-library/issues
- npm.io page: https://npm.io/package/layout-menus

## Dependencies (2)

- [tslib](https://npm.io/package/tslib.md) ^1.10.0
- [ng-zorro-antd](https://npm.io/package/ng-zorro-antd.md) ^9.3.0

## Alternatives

- [angular-pipes](https://npm.io/package/angular-pipes.md) — 5.6K weekly downloads
- [@ng-web-apis/midi](https://npm.io/package/@ng-web-apis/midi.md) — 2.6K weekly downloads
- [happn-3](https://npm.io/package/happn-3.md) — 1.6K weekly downloads
- [@opensip-cli/lang-go](https://npm.io/package/@opensip-cli/lang-go.md) — 1.2K weekly downloads
- [mongoose-typescript](https://npm.io/package/mongoose-typescript.md) — 85 weekly downloads

## Recent versions

- 2.0.2 (latest) — 2020-08-18
- 2.0.1 — 2020-08-13
- 2.0.0 — 2020-08-13
- 1.1.11 — 2020-06-07
- 1.1.10 — 2020-06-07
- 1.1.9 — 2020-06-02
- 1.1.8 — 2020-06-02
- 1.1.7 — 2020-05-29
- 1.1.6 — 2020-05-28
- 1.1.5 — 2020-05-28
- 1.1.4 — 2020-05-27
- 1.1.3 — 2020-05-27
- 1.1.2 — 2020-05-26
- 1.1.1 — 2020-05-26
- 1.0.9 — 2020-05-26
- … 43 more at https://npm.io/package/layout-menus/versions

## README

# LayoutMenus
> 满足公司内部，菜单使用 ng 9.0+;[demo地址](https://ngx-library.now.sh)

## 1、开始使用
  - <a href="#install">安装</a>
  - <a href="#use">使用</a>

## 2、使用方式

为满足系统``上下``布局和``左右``布局，支持LOGO部分存在`c-layout-header` 及`c-layout-side` 组件内 

### 菜单数据结构 `cMenuList`的`Menu`结构

| name         | description       | type              | required |
| ------------ | ----------------- | ----------------- | -------- |
| `id`         | ID;组件内部无使用 | `number` `\|` `string`| `false`  |
| `attributes` | 菜单属性集合,可以拥有自定义的属性 | `Attributes` | `true`   |
| `children`     | 子级              | `Array<Menu>`           | `false`  |
| `show`         | 是否展开          | `boolean`             | `false`|

#### 自定义数据[Attributes]

| name          | description | type  | required |
| ------------- | ----------- | ----- | -------- |
| `title`        | 标题              | `stirng`             | `true`   |
| `router`       | 路由地址          | `null` `\|` `string`  | `true` |
| `iconImage`    | 路由图标          | `string`              | `-`    |
| `notLink`      | 是否不允许跳转          | `boolean`             | `false`|
| `outSideRouter` | 是否第三方菜单  | `boolean`               | `false`    |
| `target`        | 当`outSideRouter`为`true`是，可以设置打开方式 | `_blank` `_parent` `_self` `_top` | `_blank` |


### <a href="#header">头部导航</a>

- `c-layout-header`整个顶部导航使用

### <a href="#left">左侧导航</a>

- `c-layout-side`整体左侧组件使用
- `c-layout-slider` 整体左侧菜单【基于anted】，使用方式同`c-layout-side`

### <a href="#layout">整体布局</a>

在使用组件之前先布局结构（可以按自己的结构布局）

## <a name="install">安装</a>

```javascript
npm i layout-menus --save
```

## <a name="use">使用</a>

### 项目引入`LayoutMenusModule`

``LayoutMenusModule``应用在``SharedModule``中, 具体使用方式如下。因使用到``Ant Design``需要引入``HttpClientModule`` ``BrowserAnimationsModule``;

> app.module.ts
```javascript
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { SharedModule } from './shared/shared.module';
import { AppRoutingModule } from './app-routing.module';

import { AppComponent } from './app.component';
import { NotFoundComponent } from './not-found/not-found.component';

@NgModule({
  declarations: [
    AppComponent,
    NotFoundComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    HttpClientModule,
    SharedModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

```

> shared.module.ts
```javascript
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { NgZorroAntdModule } from 'ng-zorro-antd';
import { LayoutMenusModule } from 'layout-menus';

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    RouterModule,
    FormsModule,
    ReactiveFormsModule,
    NgZorroAntdModule,
    LayoutMenusModule,
  ],
  exports: [
    NgZorroAntdModule,
    LayoutMenusModule,
  ]
})
export class SharedModule { }
```

### <a name="header">头部导航</a>

#### 参数

| Name                 | Description                                                  | type                          | required | default |
| -------------------- | ------------------------------------------------------------ | ----------------------------- | -------- | ------- |
| `[cCollapsed]`       | 左侧菜单是否展开                                             | `boolean`                     | `false`  | `false` |
| `[cIsLogo]`          | 是否在头部展示`logo`部分                                     | `boolean`                     | `false`  | `false` |
| `[cMenuList]`        | 菜单列表，当为`true`是，`[cLogoRender]`和`[cLogoConfig]`生效 | `Array`                       | `true`   | `-`     |
| `[cLogoRender]`      | 自定义`logo`区域的内容,                                      | `TemplateRef<void>`           | `false`  | `-`     |
| `[cLogoConfig]`      | `logo`不使用自定义的结构。可使用参数传值                     | `json`                        |          |         |
| `[cWidth]`           | `logo`区域的宽度                                           | `number`     |      `false`  | `180`   |
| `[cCollapsedWidth]`           | `logo`区域收起时的宽度                    | `number`     |      `false`  | `50`   |
| `[cMenuLeft]`      | 左侧菜单，可以进行自定义            |  `template: TemplateRef<{ $implicit: menu}>`   |  `false`        |    `-`     |
| `[cMenuLeftBefore]`       | 左侧菜单之前                                                     | `template: TemplateRef<void>` | `false`  | `-`     |
| `[cMenuRight]`       | 右侧菜单                                                     | `template: TemplateRef<void>` | `false`  | `-`     |
| `[isOutSideMenuOpen]` | `logo`区域外部菜单是否展开 | `boolean` | `false` | `false` |
| `(outsideMouseover)` | `logo`区域外部菜单`mouseover`事件   | `EventEmitter<$event>`      | `false`  | `-`     |
| `(outsideMouseleave)` | `logo`区域外部菜单`mouseleave`事件 | `EventEmitter<$event>` | `false` | `-`  |
| `(clickMenu)` | 点击菜单事件 | `EventEmitter<Menu>` | `false` | `-` |
| `(changeMenu)` | 菜单更改的回调 | `EventEmitter<Menu>` | `false` | `-` |

#### 精简头部菜单模式

```typescript
import { Component } from '@angular/core';
@Component({
  // tslint:disable-next-line:component-selector
  selector: 'demo-layout-header-simple',
  template: `
    <c-layout-header [cMenuList]="menuList" [cCollapsed]="isCollapsed" [cLogoRender]="null"></c-layout-header>
  `,
})
export class DemoLayoutHeaderSimpleComponent {
  public isCollapsed = false;
  public menuList = [];
}
```

#### 显示右侧菜单。

由于右侧菜单可能拥有不同的`事件`或者`样式`，所以没有设置默认模板。但是拥有一套`统一`的样式，书写时带有正确的`class`即可；

```typescript
import { Component } from '@angular/core';

@Component({
  selector: 'demo-layout-header-right-menu',
  template: `
    <c-layout-header [cMenuList]="menuList" [cCollapsed]="isCollapsed" [cLogoRender]="null" [cMenuRight]="rightMenu"></c-layout-header>
    <ng-template #rightMenu>
      <span class="layout-header-container-action">二维码</span>
      <span class="layout-header-container-action">消息通知</span>
      <span class="layout-header-container-action">个人中心</span>
      <span class="layout-header-container-action layout-header-container-action--account">泡泡糖，你好<i nz-icon nzType="down" nzTheme="outline"></i></span>
    </ng-template>
  `
})
export class DemoLayoutHeaderRightMenuComponent {
  public isCollapsed = false;
  public menuList = [];
}
```

#### 显示左侧`logo`

```typescript
import { Component } from '@angular/core';

@Component({
  selector: 'demo-layout-header-logo',
  template: `
    <c-layout-header [cMenuList]="menuList" [cCollapsed]="isCollapsed" [cIsLogo]="true" [cLogoConfig]="logoConfig" ></c-layout-header>
  `
})
export class DemoLayoutHeaderLogoComponent {
  public isCollapsed = false;
  public menuList = [];
  public logoConfig = {
    title: '权限管理',
    outsideIcon: 'menu',
    logoImg: '../assets/logo.png'
  };
}
```

### <a name="left">左侧导航</a>
#### 参数
| Name                 | Description                              | type                    | required | default |
| -------------------- | ---------------------------------------- | ----------------------- | -------- | ------- |
| `[cMenuList]`        | 菜单列表                                 | `Array`                 | `true`   | `-`     |
| `[cPaddingLeft]`     | 菜单左缩进`16 + menu._depth * cPaddingLeft` | `Array`               | `true`   | `14`     |
| `[cShowTrigger]`     | 是否显示`trigger`                       | `boolean`               | `false`  | `true` |
| `[cLogoConfig]`      | `logo`不使用自定义的结构。可使用参数传值 | `json`                  | `false`  | `-`     |
| `[cMenuTop]`         | 在菜单列表区域添加`自定义的顶部内容`     | `TemplateRef<void>`     | `false`  | `-`     |
| `[cMenuBottom]`      | 在菜单区域添加底部`自定义的内容`         | `TemplateRef<void>`     | `false`  | `-`     |
| `[cLogoRender]`      | 自定义`logo`区域的内容,                  | `TemplateRef<void>`     | `false`  | `-`     |
| `[cMenuItemRouter]`  | 自定义路由列表                           | `templateRef<void>`     | `false`  | `-`     |
| `[cCollapsed]`       | 当前收起状态                             | `boolean`               | `false`  | `false` |
| `(cCollapsedChange)` | 展开-收起时的回调函数                    | `EventEmitter<boolean>` | `false`  | `-`     |
| `[isOutSideMenuOpen]` | `logo`区域外部菜单是否展开              | `boolean`               | `false` | `false` |
| `(outsideMouseover)`  | `logo`区域外部菜单`mouseover`事件       | `EventEmitter<$event>`  | `false`  | `-`     |
| `(outsideMouseleave)` | `logo`区域外部菜单`mouseleave`事件      | `EventEmitter<$event>`  | `false` | `-`  |
| `(clickMenu)` | 点击左侧导航事件 | `EventEmitter<menu>` | `false` | `-` |

#### 简单使用
简单使用，只留有菜单部分；

```typescript
import { Component } from '@angular/core';

@Component({
  selector: 'demo-layout-side-simple',
  template: `
  <nz-sider nzCollapsible [(nzCollapsed)]="isCollapsed" [nzTrigger]="null" [nzCollapsedWidth]="isCollapsed ? 50 : 200">
    <c-layout-side [cMenuList]="menuList" [(cCollapsed)]="isCollapsed" [cLogoRender]="null"></c-layout-side>
  </nz-sider>
  `,
  styles: [`
  nz-sider {
    position: fixed;
    top: 0px;
    bottom: 0;
    box-shadow: 5px 0 4px -4px #ddd;
  }
  `]
})
export class DemoLayoutSideSimpleComponent {
  public isCollapsed = false;
  public menuList = [];
}
```

#### 带有logo模式

```typescript
import { Component } from '@angular/core';

@Component({
  selector: 'demo-layout-side-logo',
  template: `
  <nz-sider nzCollapsible [(nzCollapsed)]="isCollapsed" [nzTrigger]="null" [nzCollapsedWidth]="isCollapsed ? 50 : 200">
    <c-layout-side [cMenuList]="menuList" [(cCollapsed)]="isCollapsed" [cLogoConfig]="logoConfig"></c-layout-side>
  </nz-sider>
  `,
  styles: [`
  nz-sider {
    position: fixed;
    top: 0px;
    bottom: 0;
    box-shadow: 5px 0 4px -4px #ddd;
  }
  `]
})
export class DemoLayoutSideLogoComponent {
  public isCollapsed = false;
  public menuList = [];
  public logoConfig = {
    title: '权限管理',
    outsideIcon: 'menu',
    logoImg: '../assets/logo.png'
  };
}
```

#### 自定义LOGO区域

```typescript
import { Component } from '@angular/core';

@Component({
  selector: 'demo-layout-side-simple',
  template: `
  <nz-sider nzCollapsible [(nzCollapsed)]="isCollapsed" [nzTrigger]="null" [nzCollapsedWidth]="isCollapsed ? 50 : 200">
    <c-layout-side [cMenuList]="menuList" [(cCollapsed)]="isCollapsed" [cLogoRender]="LogoTemplate"></c-layout-side>
  </nz-sider>
  <ng-template #LogoTemplate>
    <a href="">
      <div class="global-app-menu-logo" [class.global-app-menu-logo--collapsed]="isCollapsed">
        <span class="global-app-menu-logo--title">我是头部的Logo</span>
      </div>
    </a>
  </ng-template>
  `,
  styles: [`
  nz-sider {
    position: fixed;
    top: 0px;
    bottom: 0;
    box-shadow: 5px 0 4px -4px #ddd;
  }
  `]
})
export class DemoLayoutHeaderRightMenuComponent {
  public isCollapsed = false;
  public menuList = [];
}
```

#### 自定义菜单列表`item`

```typescript
import { Component } from '@angular/core';

@Component({
  // tslint:disable-next-line:component-selector
  selector: 'demo-layout-side-custom-menu-item-router',
  template: `
    <nz-sider nzCollapsible [(nzCollapsed)]="isCollapsed" [nzTrigger]="null" [nzCollapsedWidth]="isCollapsed ? 50 : 200">
    <c-layout-side
      [cMenuList]="menuList"
      [(cCollapsed)]="isCollapsed"
      [cLogoConfig]="logoConfig"
      [cMenuItemRouter]="menuItemTemplate"
      ></c-layout-side>
    </nz-sider>

    <ng-template #menuItemTemplate let-menu let-size="size">
      <ng-container *ngIf="menu.attributes.subMenu">
        <div
          nz-tooltip
          [nzTooltipTitle]="isCollapsed ? menu?.attributes?.title : ''"
          nzTooltipPlacement="right"
          class="menu-item"
          [routerLink]="menu.attributes.router"
          routerLinkActive
          #routerRef="routerLinkActive"
          [class.active]="routerRef.isActive && menu.attributes.router"
          [class.open]="menu.show"
        >
          <img [style.width.px]="size" [src]="sanitizer.bypassSecurityTrustUrl(menu.attributes.iconImage)">
            自定义属性subMenu
          <i class="menu-more" nz-icon nzType="right" nzTheme="outline" (click)="expandMore($event, menu)"></i>
        </div>
      </ng-container>

      <ng-container *ngIf="!menu.attributes.subMenu">
        <a class="menu-item" [style.paddingLeft.px]="16 + (cCollapsed ? 0 : (menu?._depth * 12))">
          <img *ngIf="menu?.attributes?.iconImage" [style.width.px]="size" [src]="sanitizer.bypassSecurityTrustUrl(menu.attributes.iconImage)">
          <span>{{menu.attributes.title}}<span>
          <i *ngIf="menu.children && menu.children.length" class="menu-more" nz-icon nzType="right" nzTheme="outline"></i>
        </a>
      </ng-container>
    </ng-template>
  `,
  styles: [`
  nz-sider {
    position: fixed;
    top: 0px;
    bottom: 0;
    box-shadow: 5px 0 4px -4px #ddd;
  }

  nz-content {
    margin: 0 16px;
  }

  c-layout-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    transition: all .2s;
  }
  `]
})
export class DemoLayoutSideCustomMenuItemRouterComponent {
  public isCollapsed = false;
  public menuList = [
    ...
    {
      id: 104,
      attributes: {
        router: null,
        subMenu: true,
        // tslint:disable-next-line:max-line-length
        iconImage: '',
        icon: 'iconfont icon-guanli',
        title: '审批管理'
      },
      children: [
        {
          id: 106,
          attributes: {
            router: '/approval/authority-approval',
            iconImage: null,
            icon: 'authority-approval',
            title: '权限审批'
          },
          children: []
        }
      ]
    }
  ];
  logoConfig = {
    title: '权限管理',
    outsideIcon: 'menu',
    logoImg: '../assets/logo.png'
  };
}
```

#### 菜单列表增加自定义头部和底部

```typescript
import { Component } from '@angular/core';

@Component({
  selector: 'demo-layout-side-custom-top-and-bottom',
  template: `
  <nz-sider nzCollapsible [(nzCollapsed)]="isCollapsed" [nzTrigger]="null" [nzCollapsedWidth]="isCollapsed ? 50 : 200">
    <c-layout-side
      [cMenuList]="menuList"
      [(cCollapsed)]="isCollapsed"
      [cLogoConfig]="logoConfig"
      [cMenuTop]="menuTop"
      [cMenuBottom]="menuBottom"
    ></c-layout-side>
  </nz-sider>

  <ng-template #menuTop>
    <div *ngIf="!isCollapsed">菜单列表自定义顶部</div>
  </ng-template>

  <ng-template #menuBottom>
    <div *ngIf="!isCollapsed">菜单列表自定义顶部</div>
  </ng-template>
  `,
  styles: [`
  nz-sider {
    position: fixed;
    top: 0px;
    bottom: 0;
    box-shadow: 5px 0 4px -4px #ddd;
  }
  div {
    height: 64px;
    line-height: 64px;
    text-align: center;
    background: #e4e4e4;
  }
  `]
})
export class DemoLayoutSideCustomTopAndBottomComponent {
  public isCollapsed = false;
  public menuList = [];
}
```

### <a name="layout">整体结构</a>

#### logo在左侧布局

```typescript
import { Component } from '@angular/core';

@Component({
  // tslint:disable-next-line:component-selector
  selector: 'demo-layout-logo-left',
  template: `
  <nz-layout>
    <nz-sider nzCollapsible [(nzCollapsed)]="isCollapsed" [nzTrigger]="null" [nzCollapsedWidth]="isCollapsed ? 50 : 200">
      <c-layout-side [cMenuList]="menuList" [(cCollapsed)]="isCollapsed" [cLogoConfig]="logoConfig"></c-layout-side>
    </nz-sider>
    <nz-layout [style.marginLeft.px]="isCollapsed ? 50 : 200" [style.marginTop.px]="50">
      <c-layout-header
        [cMenuList]="menuList"
        [cCollapsed]="isCollapsed"
        [cLogoRender]="null"
        [cMenuRight]="rightMenu"
        [style.left.px]="isCollapsed ? 50 : 200"
      ></c-layout-header>
      <nz-content style="margin:0 16px;">
        <div style="padding:24px; background: #fff; min-height: 1360px; margin-top: 20px;">
          <router-outlet></router-outlet>
        </div>
      </nz-content>
    </nz-layout>
  </nz-layout>
  `,
  styles: [`
  nz-sider {
    position: fixed;
    top: 0px;
    bottom: 0;
    box-shadow: 5px 0 4px -4px #ddd;
  }

  nz-content {
    margin: 0 16px;
  }

  c-layout-header {
    position: fixed;
    top: 0;
	left: 0;
    right: 0;
    transition: all .2s;
  }
  `]
})
export class DemoLayoutLogoLeftComponent {
  public isCollapsed = false;
  public menuList = [];
  logoConfig = {
    title: '权限管理',
    outsideIcon: 'menu',
    logoImg: '../assets/logo.png'
  };
}
```

#### LOGO在顶部布局
样式效果，同`LOGO`在左侧布局效果一样；

```typescript
import { Component } from '@angular/core';

@Component({
  selector: 'demo-layout-logo-top',
  template: `
  <nz-layout>
    <nz-sider nzCollapsible [(nzCollapsed)]="isCollapsed" [nzTrigger]="null" [nzCollapsedWidth]="isCollapsed ? 50 : 200">
      <c-layout-side [cMenuList]="menuList" [(cCollapsed)]="isCollapsed" [cLogoRender]="null"></c-layout-side>
    </nz-sider>
    <nz-layout [style.marginLeft.px]="isCollapsed ? 50 : 200" [style.marginTop.px]="50">
      <c-layout-header
        [cMenuList]="menuList"
        [cCollapsed]="isCollapsed"
        [cIsLogo]="true"
        [cLogoConfig]="logoConfig"
      [cMenuRight]="rightMenu"></c-layout-header>
      <nz-content style="margin:0 16px;">
        <div style="padding:24px; background: #fff; min-height: 1360px; margin-top: 20px;">
          <router-outlet></router-outlet>
        </div>
      </nz-content>
    </nz-layout>
  </nz-layout>
  `,
  styles: [`
  nz-sider {
    position: fixed;
    top: 50px;
    bottom: 0;
    box-shadow: 5px 0 4px -4px #ddd;
  }

  nz-content {
    margin: 0 16px;
  }

  c-layout-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    transition: all .2s;
  }
  `]
})
export class DemoLayoutLogoTopComponent {
  public isCollapsed = false;
  public menuList = [];
  logoConfig = {
    title: '权限管理',
    outsideIcon: 'menu',
    logoImg: '../assets/logo.png'
  };
}

```

---
_Source: https://npm.io/package/layout-menus · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
