Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(module:cascader): refactor cascader #2516

Merged
merged 3 commits into from
Nov 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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