项目初始化
This commit is contained in:
16
src/app/shared/components/address/address.component.html
Normal file
16
src/app/shared/components/address/address.component.html
Normal file
@ -0,0 +1,16 @@
|
||||
<nz-cascader
|
||||
*ngIf="data"
|
||||
[(ngModel)]="value"
|
||||
(ngModelChange)="change()"
|
||||
[nzOptions]="data"
|
||||
[nzDisabled]="disabled"
|
||||
[nzAllowClear]="allowClear"
|
||||
[nzAutoFocus]="autoFocus"
|
||||
[nzNotFoundContent]="notFoundContent"
|
||||
[nzSize]="size"
|
||||
[nzShowSearch]="showSearch"
|
||||
[nzPlaceHolder]="placeHolder"
|
||||
[nzMouseEnterDelay]="mouseEnterDelay"
|
||||
[nzMouseLeaveDelay]="mouseLeaveDelay"
|
||||
[nzTriggerAction]="triggerAction"
|
||||
></nz-cascader>
|
||||
84
src/app/shared/components/address/address.component.ts
Normal file
84
src/app/shared/components/address/address.component.ts
Normal file
@ -0,0 +1,84 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, forwardRef, Input, OnInit } from '@angular/core';
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
import { BooleanInput, InputBoolean } from '@delon/util';
|
||||
import {
|
||||
NzCascaderExpandTrigger,
|
||||
NzCascaderOption,
|
||||
NzCascaderSize,
|
||||
NzCascaderTriggerType,
|
||||
NzShowSearchOptions
|
||||
} from 'ng-zorro-antd/cascader';
|
||||
|
||||
import { AddressService, AddressType } from './address.service';
|
||||
|
||||
@Component({
|
||||
selector: 'address',
|
||||
templateUrl: './address.component.html',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: forwardRef(() => AddressComponent),
|
||||
multi: true
|
||||
}
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class AddressComponent implements OnInit, ControlValueAccessor {
|
||||
static ngAcceptInputType_allowClear: BooleanInput;
|
||||
static ngAcceptInputType_autoFocus: BooleanInput;
|
||||
static ngAcceptInputType_disabled: BooleanInput;
|
||||
|
||||
private onChangeFn?: (val: string) => void;
|
||||
private onTouchedFn?: () => void;
|
||||
value: string[] = [];
|
||||
data?: NzCascaderOption[];
|
||||
|
||||
// #region fields
|
||||
|
||||
@Input() type: AddressType = 'pca';
|
||||
|
||||
// Original attributes
|
||||
@Input() @InputBoolean() allowClear = true;
|
||||
@Input() @InputBoolean() autoFocus = false;
|
||||
@Input() @InputBoolean() disabled = false;
|
||||
@Input() expandTrigger: NzCascaderExpandTrigger = 'click';
|
||||
@Input() notFoundContent?: string;
|
||||
@Input() size: NzCascaderSize = 'default';
|
||||
@Input() showSearch!: boolean | NzShowSearchOptions;
|
||||
@Input() placeHolder = '请选择所在地';
|
||||
@Input() mouseEnterDelay = 150; // ms
|
||||
@Input() mouseLeaveDelay = 150; // ms
|
||||
@Input() triggerAction: NzCascaderTriggerType | NzCascaderTriggerType[] = ['click'] as NzCascaderTriggerType[];
|
||||
|
||||
// #endregion
|
||||
|
||||
constructor(private srv: AddressService, private cdr: ChangeDetectorRef) {}
|
||||
|
||||
change(): void {
|
||||
this.onChangeFn!(this.value.pop()!);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.srv[this.type].subscribe(res => {
|
||||
this.data = res;
|
||||
this.cdr.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
writeValue(geo: string): void {
|
||||
if (geo == null) {
|
||||
this.value = [];
|
||||
return;
|
||||
}
|
||||
this.value = this.srv.toValueArr(geo, this.type);
|
||||
}
|
||||
registerOnChange(fn: any): void {
|
||||
this.onChangeFn = fn;
|
||||
}
|
||||
registerOnTouched(fn: any): void {
|
||||
this.onTouchedFn = fn;
|
||||
}
|
||||
setDisabledState?(isDisabled: boolean): void {
|
||||
this.disabled = isDisabled;
|
||||
}
|
||||
}
|
||||
15
src/app/shared/components/address/address.module.ts
Normal file
15
src/app/shared/components/address/address.module.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { NzCascaderModule } from 'ng-zorro-antd/cascader';
|
||||
|
||||
import { AddressComponent } from './address.component';
|
||||
|
||||
const COMPONENTS = [AddressComponent];
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, FormsModule, NzCascaderModule],
|
||||
declarations: COMPONENTS,
|
||||
exports: COMPONENTS
|
||||
})
|
||||
export class AddressModule {}
|
||||
79
src/app/shared/components/address/address.service.ts
Normal file
79
src/app/shared/components/address/address.service.ts
Normal file
@ -0,0 +1,79 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { _HttpClient } from '@delon/theme';
|
||||
import { ArrayService } from '@delon/util';
|
||||
import { NzCascaderOption } from 'ng-zorro-antd/cascader';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
export interface PCCode {
|
||||
code?: string;
|
||||
name?: string;
|
||||
value?: string;
|
||||
label?: string;
|
||||
isLeaf?: boolean;
|
||||
children?: PCCode[];
|
||||
}
|
||||
|
||||
export type AddressType = 'pc' | 'pca';
|
||||
const MAXLENGTH = 6;
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddressService {
|
||||
private _pcCode?: NzCascaderOption[];
|
||||
private _pcaCode?: NzCascaderOption[];
|
||||
|
||||
/**
|
||||
* “省份、城市” 二级联动数据,数据来源于 [pc-code.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/pc-code.json)
|
||||
*/
|
||||
get pc(): Observable<NzCascaderOption[]> {
|
||||
return this._pcCode ? of(this._pcCode) : this.getPcCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* “省份、城市、区县” 三级联动数据,数据来源于 [pc-code.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/pca-code.json)
|
||||
*/
|
||||
get pca(): Observable<NzCascaderOption[]> {
|
||||
return this._pcaCode ? of(this._pcaCode) : this.getPcaCode();
|
||||
}
|
||||
|
||||
constructor(private http: _HttpClient, private arrSrv: ArrayService) {}
|
||||
|
||||
/**
|
||||
* 始终保持 6 位数,不足补 `0`
|
||||
*/
|
||||
fixValue(val: string): string {
|
||||
return `${val}000000`.substr(0, MAXLENGTH);
|
||||
}
|
||||
|
||||
toValueArr(val: string, type: AddressType): string[] {
|
||||
val = this.fixValue(val);
|
||||
const res: string[] = [];
|
||||
if (type === 'pc') {
|
||||
res.push(val.substr(0, 2), val);
|
||||
} else {
|
||||
for (let i = 0; i < MAXLENGTH; i += 2) {
|
||||
res.push(val.substr(0, i + 2));
|
||||
}
|
||||
}
|
||||
return res.map(this.fixValue);
|
||||
}
|
||||
|
||||
private map = (res: PCCode[]): NzCascaderOption[] => {
|
||||
this.arrSrv.visitTree(res, (item: PCCode) => {
|
||||
item.value = this.fixValue(item.code!);
|
||||
item.label = item.name;
|
||||
if (!item.children) {
|
||||
item.isLeaf = true;
|
||||
}
|
||||
});
|
||||
return res;
|
||||
};
|
||||
|
||||
private getPcCode(): Observable<NzCascaderOption[]> {
|
||||
return this.http.get('./assets/tmp/pc-code.json').pipe(map(this.map));
|
||||
}
|
||||
|
||||
private getPcaCode(): Observable<NzCascaderOption[]> {
|
||||
return this.http.get('./assets/tmp/pca-code.json').pipe(map(this.map));
|
||||
}
|
||||
}
|
||||
26
src/app/shared/components/address/index.en-US.md
Normal file
26
src/app/shared/components/address/index.en-US.md
Normal file
@ -0,0 +1,26 @@
|
||||
---
|
||||
order: 110
|
||||
title: address
|
||||
type: Component
|
||||
---
|
||||
|
||||
China address picker, support two styles of “province, city” or “province, city, district”, refer to the account management example.
|
||||
|
||||
## API
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
|----------|----|----------|--------|
|
||||
| `[ngModel]` | selected value, return the city or district code | `string` | - |
|
||||
| `[type]` | Type of address | `pc,pca` | `pca` |
|
||||
| `[allowClear]` | whether allow clear | `boolean` | `true` |
|
||||
| `[autoFocus]` | whether auto focus the input box | `boolean` | `false` |
|
||||
| `[disabled]` | whether disabled select | `boolean` | `false` |
|
||||
| `[expandTrigger]` | expand current item when click or hover, one of 'click' 'hover' | `'click'|'hover'` | `'click'` |
|
||||
| `[notFoundContent]` | Specify content to show when no result matches. | `string` | - |
|
||||
| `[placeHolder]` | input placeholder | `string` | `'请选择所在地'` |
|
||||
| `[showSearch]` | Whether support search. Cannot be used with `[nzLoadData]` at the same time | `boolean|NzShowSearchOptions` | `false` |
|
||||
| `[size]` | input size, one of `large` `default` `small` | `'large'|'small'|'default'` | `'default'` |
|
||||
|
||||
## sf widget
|
||||
|
||||
Widget name: `address`.
|
||||
3
src/app/shared/components/address/index.ts
Normal file
3
src/app/shared/components/address/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './address.service';
|
||||
export * from './address.component';
|
||||
export * from './address.module';
|
||||
26
src/app/shared/components/address/index.zh-CN.md
Normal file
26
src/app/shared/components/address/index.zh-CN.md
Normal file
@ -0,0 +1,26 @@
|
||||
---
|
||||
order: 110
|
||||
title: address
|
||||
type: Component
|
||||
---
|
||||
|
||||
地址选择器,支持“省份、城市”或“省份、城市、区县”两种风格,参考账号管理示例。
|
||||
|
||||
## API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|----------|----|----------|--------|
|
||||
| `[ngModel]` | 指定选中项,返回城市或区县代码 | `string` | - |
|
||||
| `[type]` | 类型 | `pc,pca` | `pca` |
|
||||
| `[allowClear]` | 是否支持清除 | `boolean` | `true` |
|
||||
| `[autoFocus]` | 是否自动聚焦,当存在输入框时 | `boolean` | `false` |
|
||||
| `[disabled]` | 禁用 | `boolean` | `false` |
|
||||
| `[expandTrigger]` | 次级菜单的展开方式,可选 'click' 和 'hover' | `'click'|'hover'` | `'click'` |
|
||||
| `[notFoundContent]` | 当下拉列表为空时显示的内容 | `string` | - |
|
||||
| `[placeHolder]` | 输入框占位文本 | `string` | `'请选择所在地'` |
|
||||
| `[showSearch]` | 是否支持搜索,默认情况下对 `label` 进行全匹配搜索,不能和 `[nzLoadData]` 同时使用 | `boolean|NzShowSearchOptions` | `false` |
|
||||
| `[size]` | 输入框大小,可选 `large` `default` `small` | `'large'|'small'|'default'` | `'default'` |
|
||||
|
||||
## sf 小部件
|
||||
|
||||
小部件名称:`address`。
|
||||
Reference in New Issue
Block a user