Skip to content

Commit

Permalink
refactor(module:cascader): refactor cascader
Browse files Browse the repository at this point in the history
close #2935, #2198
  • Loading branch information
Wendell committed Nov 23, 2018
1 parent 3b8f9ea commit 01ec4dd
Show file tree
Hide file tree
Showing 18 changed files with 929 additions and 1,173 deletions.
15 changes: 15 additions & 0 deletions components/cascader/demo/custom-field-names.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
order: 16
title:
zh-CN: 自定义字段名
en-US: Custom Field Names
---

## zh-CN

自定义字段名。

## en-US

Custom field names.

73 changes: 73 additions & 0 deletions components/cascader/demo/custom-field-names.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// tslint:disable:no-any
import { Component } from '@angular/core';

const options = [{
code: 'zhejiang',
name: 'Zhejiang',
children: [{
code: 'hangzhou',
name: 'Hangzhou',
children: [{
code: 'xihu',
name: 'West Lake',
isLeaf: true
}]
}, {
code: 'ningbo',
name: 'Ningbo',
children: [{
code: 'dongqianlake',
name: 'Dongqian Lake',
isLeaf: true
}]
}]
}, {
code: 'jiangsu',
name: 'Jiangsu',
children: [{
code: 'nanjing',
name: 'Nanjing',
children: [{
code: 'zhonghuamen',
name: 'Zhong Hua Men',
isLeaf: true
}]
}]
}];

@Component({
selector: 'nz-demo-cascader-custom-field-names',
template: `
<nz-cascader
[nzChangeOn]="validate"
[nzOptions]="nzOptions"
[nzLabelProperty]="'name'"
[nzValueProperty]="'code'"
[nzShowSearch]="true"
[(ngModel)]="values"
(ngModelChange)="onChanges($event)">
</nz-cascader>`,
styles : [
`
.ant-cascader-picker {
width: 300px;
}
`
]
})
export class NzDemoCascaderCustomFieldNamesComponent {
/** init data */
nzOptions = options;

/** ngModel value */
public values: any[] = null;

public onChanges(values: any): void {
console.log(values, this.values);
}

public validate(option: any, index: number): boolean {
const value = option.value;
return ['hangzhou', 'xihu', 'nanjing', 'zhonghuamen'].indexOf(value) >= 0;
}
}
1 change: 1 addition & 0 deletions components/cascader/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Cascade selection box.
| `[nzExpandTrigger]` | expand current item when click or hover, one of 'click' 'hover' | string | 'click' |
| `[nzMenuClassName]` | additional className of popup overlay | string | - |
| `[nzMenuStyle]` | additional css style of popup overlay | object | - |
| `[nzNotFoundContent]` | Specify content to show when no result matches. | string | - |
| `[nzLabelProperty]` | the label property name of options | string | 'label' |
| `[nzLabelRender]` | render template of displaying selected options | TemplateRef&lt;any&gt; | - |
| `[nzLoadData]` | To load option lazily. If setting `ngModel` with an array value and `nzOptions` is not setting, lazy load will be call immediately | (option: any, index?: index) => PromiseLike&lt;any&gt; | - |
Expand Down
1 change: 1 addition & 0 deletions components/cascader/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ subtitle: 级联选择
| `[nzExpandTrigger]` | 次级菜单的展开方式,可选 'click' 和 'hover' | string | 'click' |
| `[nzMenuClassName]` | 自定义浮层类名 | string | - |
| `[nzMenuStyle]` | 自定义浮层样式 | object | - |
| `[nzNotFoundContent]` | 当下拉列表为空时显示的内容 | string | - |
| `[nzLabelProperty]` | 选项的显示值的属性名 | string | 'label' |
| `[nzLabelRender]` | 选择后展示的渲染模板 | TemplateRef&lt;any&gt; | - |
| `[nzLoadData]` | 用于动态加载选项。如果提供了`ngModel`初始值,且未提供`nzOptions`值,则会立即触发动态加载。 | (option: any, index?: index) => PromiseLike&lt;any&gt; | - |
Expand Down
9 changes: 9 additions & 0 deletions components/cascader/nz-cascader-li.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<ng-container *ngIf="highlightText">
<span [innerHTML]="renderHighlightString(getOptionLabel())"></span>
</ng-container>
<ng-container *ngIf="!highlightText">
{{ getOptionLabel() }}
</ng-container>
<span *ngIf="!option.isLeaf || option.children && option.children.length || option.loading" class="ant-cascader-menu-item-expand-icon">
<i nz-icon [type]="option.loading ? 'loading' : 'right'"></i>
</span>
47 changes: 47 additions & 0 deletions components/cascader/nz-cascader-li.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Component, Input, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { classMapToString } from '../core/style/map';
import { CascaderOption } from './types';

const prefixCls = 'ant-cascader-menu-item';

@Component({
selector : '[nz-cascader-option]',
templateUrl: './nz-cascader-li.component.html',
host : {
'[attr.title]': 'option.title || getOptionLabel()',
'[class]' : 'getOptionClassString()'
}
})
export class NzCascaderOptionComponent {
@Input() option: CascaderOption;
@Input() activated = false;
@Input() highlightText: string;
@Input() nzLabelProperty = 'label';

getOptionLabel(): string {
return this.option ? this.option[ this.nzLabelProperty ] : '';
}

getOptionClassString(): string {
return classMapToString({
[ `${prefixCls}` ] : true,
[ `${prefixCls}-active` ] : this.activated,
[ `${prefixCls}-expand` ] : !this.option.isLeaf,
[ `${prefixCls}-disabled` ]: this.option.disabled
});
}

renderHighlightString(str: string): string {
const safeHtml = this.sanitizer.sanitize(
SecurityContext.HTML, `<span class="ant-cascader-menu-item-keyword">${this.highlightText}</span>`
);
if (!safeHtml) {
throw new Error(`[NG-ZORRO] Input value "${this.highlightText}" is not considered security.`);
}
return str.replace(new RegExp(this.highlightText, 'g'), safeHtml);
}

constructor(private sanitizer: DomSanitizer) {
}
}
85 changes: 36 additions & 49 deletions components/cascader/nz-cascader.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,26 @@
#trigger>
<div *ngIf="nzShowInput">
<input #input
nz-input
[attr.autoComplete]="'off'"
[attr.placeholder]="showPlaceholder ? nzPlaceHolder : null"
[attr.autofocus]="nzAutoFocus ? 'autofocus' : null"
[readonly]="!nzShowSearch"
[disabled]="nzDisabled"
[nzSize]="nzSize"
[ngClass]="inputCls"
[(ngModel)]="inputValue"
(blur)="handleInputBlur($event)"
(focus)="handleInputFocus($event)"
(change)="handlerInputChange($event)">
<i *ngIf="showClearIcon"
nz-icon
type="close-circle"
theme="fill"
[ngClass]="clearCls"
[attr.title]="nzClearText"
(click)="clearSelection($event)"></i>
<i *ngIf="nzShowArrow && !isLoading"
nz-icon
type="down"
[ngClass]="arrowCls"></i>
<i *ngIf="isLoading"
nz-icon
type="loading"
[ngClass]="loadingCls"></i>
nz-input
[attr.autoComplete]="'off'"
[attr.placeholder]="showPlaceholder ? nzPlaceHolder : null"
[attr.autofocus]="nzAutoFocus ? 'autofocus' : null"
[readonly]="!nzShowSearch"
[disabled]="nzDisabled"
[nzSize]="nzSize"
[ngClass]="inputCls"
[(ngModel)]="inputValue"
(blur)="handleInputBlur($event)"
(focus)="handleInputFocus($event)"
(change)="$event.stopPropagation()">
<i *ngIf="clearIconVisible"
nz-icon
type="close-circle"
theme="fill"
class="ant-cascader-picker-clear"
(click)="clearSelection($event)"></i>
<i *ngIf="nzShowArrow && !isLoading" nz-icon type="down" [ngClass]="arrowCls"></i>
<i *ngIf="isLoading" nz-icon type="loading" class="ant-cascader-picker-arrow"></i>
<span [ngClass]="labelCls">
<ng-container *ngIf="!isLabelRenderTemplate; else labelTemplate">{{ labelRenderText }}</ng-container>
<ng-template #labelTemplate>
Expand All @@ -50,29 +43,23 @@
(positionChange)="onPositionChange($event)"
[cdkConnectedOverlayOpen]="menuVisible">
<div #menu
[ngClass]="menuCls" [ngStyle]="nzMenuStyle"
[@dropDownAnimation]="dropDownPosition"
(mouseleave)="onTriggerMouseLeave($event)">
<ul *ngFor="let options of nzColumns; let i = index;" [ngClass]="menuColumnCls"
[style.height]="inSearch && !nzColumns[0].length ? 'auto': ''" [style.width]="searchWidthStyle">
<li *ngFor="let option of options"
[attr.title]="option.title || getOptionLabel(option)"
[ngClass]="getOptionCls(option, i)"
(mouseenter)="onOptionMouseEnter(option, i, $event)"
(mouseleave)="onOptionMouseLeave(option, i, $event)"
(click)="onOptionClick(option, i, $event)">
<ng-container *ngIf="inSearch">
<span [innerHTML]="renderSearchString(getOptionLabel(option))"></span>
</ng-container>
<ng-container *ngIf="!inSearch">
{{ getOptionLabel(option) }}
</ng-container>
<span *ngIf="!option.isLeaf || option.children && option.children.length || option.loading" class="ant-cascader-menu-item-expand-icon">
<i nz-icon [type]="option.loading ? 'loading' : 'right'"></i>
</span>
[ngClass]="menuCls" [ngStyle]="nzMenuStyle"
[@dropDownAnimation]="dropDownPosition"
(mouseleave)="onTriggerMouseLeave($event)">
<ul *ngFor="let options of columns; let i = index;" [ngClass]="menuColumnCls"
[style.height]="isSearching && !columns[0].length ? 'auto': ''" [style.width]="dropdownWidthStyle">
<li nz-cascader-option
*ngFor="let option of options"
[nzLabelProperty]="nzLabelProperty"
[activated]="isOptionActivated(option, i)"
[highlightText]="isSearching ? inputValue : ''"
[option]="option"
(mouseenter)="onOptionMouseEnter(option, i, $event)"
(mouseleave)="onOptionMouseLeave(option, i, $event)"
(click)="onOptionClick(option, i, $event)">
</li>
<li *ngIf="inSearch && !nzColumns[0].length" class="ant-cascader-menu-item ant-cascader-menu-item-expanded ant-cascader-menu-item-disabled">
Not Found
<li *ngIf="isSearching && !columns[0].length" class="ant-cascader-menu-item ant-cascader-menu-item-expanded ant-cascader-menu-item-disabled">
{{ nzNotFoundContent || ('Select.notFoundContent' | nzI18n) }}
</li>
</ul>
</div>
Expand Down
8 changes: 8 additions & 0 deletions components/cascader/nz-cascader.component.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.ant-cascader-menus {
margin-top: 4px;
margin-bottom: 4px;
top: 100%;
left: 0;
position: relative;
width: 100%;
}
Loading

0 comments on commit 01ec4dd

Please sign in to comment.