Skip to content

Commit

Permalink
refactor(module:cascader): refactor cascader (#2516)
Browse files Browse the repository at this point in the history
* refactor(module:cascader): refactor cascader

close #2935
ref #2198

* fix(module:cascader): fix isFocused access
  • Loading branch information
Wendell authored and vthinkxie committed Nov 30, 2018
1 parent b669751 commit a7fc06d
Show file tree
Hide file tree
Showing 16 changed files with 861 additions and 1,163 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
5 changes: 5 additions & 0 deletions components/cascader/nz-cascader-li.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<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>
37 changes: 37 additions & 0 deletions components/cascader/nz-cascader-li.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ChangeDetectionStrategy, Component, Input, SecurityContext, ViewEncapsulation } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { CascaderOption } from './types';

@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation : ViewEncapsulation.None,
selector : '[nz-cascader-option]',
templateUrl : './nz-cascader-li.component.html',
host : {
'[attr.title]' : 'option.title || getOptionLabel()',
'[class.ant-cascader-menu-item]' : 'true',
'[class.ant-cascader-menu-item-active]' : 'activated',
'[class.ant-cascader-menu-item-expand]' : '!option.isLeaf',
'[class.ant-cascader-menu-item-disabled]': 'option.disabled'
}
})
export class NzCascaderOptionComponent {
@Input() option: CascaderOption;
@Input() activated = false;
@Input() highlightText: string;
@Input() nzLabelProperty = 'label';

constructor(private sanitizer: DomSanitizer) {}

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

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);
}
}
76 changes: 40 additions & 36 deletions components/cascader/nz-cascader.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,40 @@
#origin="cdkOverlayOrigin"
#trigger>
<div *ngIf="nzShowInput">
<input #input
<input
#input
nz-input
class="ant-cascader-input"
[class.ant-cascader-input-disabled]="nzDisabled"
[class.ant-cascader-input-lg]="nzSize === 'large'"
[class.ant-cascader-input-sm]="nzSize === 'small'"
[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>
(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"
[ngClass]="loadingCls"></i>
<span [ngClass]="labelCls">
nz-icon
type="down"
class="ant-cascader-picker-arrow"
[class.ant-cascader-picker-arrow-expand]="menuVisible">
</i>
<i *ngIf="isLoading" nz-icon type="loading" class="ant-cascader-picker-arrow"></i>
<span
class="ant-cascader-picker-label"
[class.ant-cascader-show-search]="!!nzShowSearch"
[class.ant-focusd]="!!nzShowSearch && isFocused && !inputValue">
<ng-container *ngIf="!isLabelRenderTemplate; else labelTemplate">{{ labelRenderText }}</ng-container>
<ng-template #labelTemplate>
<ng-template [ngTemplateOutlet]="nzLabelRender" [ngTemplateOutletContext]="labelRenderContext"></ng-template>
Expand All @@ -49,30 +54,29 @@
(detach)="closeMenu()"
(positionChange)="onPositionChange($event)"
[cdkConnectedOverlayOpen]="menuVisible">
<div #menu
[ngClass]="menuCls" [ngStyle]="nzMenuStyle"
<div
#menu
class="ant-cascader-menus"
[class.ant-cascader-menus-hidden]="!menuVisible"
[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)"
<ul *ngFor="let options of columns; let i = index;" class="ant-cascader-menu" [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)">
<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>
</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
Loading

0 comments on commit a7fc06d

Please sign in to comment.