Skip to content

Commit

Permalink
fix(form:autocomplete,select): fix return original data in change p…
Browse files Browse the repository at this point in the history
…roperty (#985)
  • Loading branch information
cipchk committed Jul 4, 2020
1 parent 7cd5b49 commit 7d70629
Show file tree
Hide file tree
Showing 14 changed files with 160 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
[attr.disabled]="disabled"
[nzSize]="ui.size"
[(ngModel)]="typing"
(ngModelChange)="setValue($event)"
(ngModelChange)="_setValue($event)"
[attr.maxLength]="schema.maxLength || null"
[attr.placeholder]="ui.placeholder"
autocomplete="off"
Expand All @@ -19,7 +19,7 @@
[nzWidth]="i.width"
(selectionChange)="updateValue($event)"
>
<nz-auto-option *ngFor="let i of list | async" [nzValue]="i.value" [nzLabel]="i.label">
<nz-auto-option *ngFor="let i of list | async" [nzValue]="i" [nzLabel]="i.label">
{{i.label}}
</nz-auto-option>
</nz-autocomplete>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { createTestContext } from '@delon/testing';
import { AlainConfigService } from '@delon/util';
import { of } from 'rxjs';
import { configureSFTestSuite, SFPage, TestFormComponent } from '../../../spec/base.spec';
import { SFSchemaEnum } from '../../../src/schema/index';
import { SFSchema, SFSchemaEnum } from '../../../src/schema/index';
import { mergeConfig } from '../../config';
import { AutoCompleteWidget } from './autocomplete.widget';
import { SFAutoCompleteWidgetSchema } from './schema';

describe('form: widget: autocomplete', () => {
let fixture: ComponentFixture<TestFormComponent>;
Expand Down Expand Up @@ -40,6 +41,28 @@ describe('form: widget: autocomplete', () => {
page.asyncEnd();
}));

it('#change', () => {
const s: SFSchema = {
properties: {
a: {
type: 'string',
title: '状态',
enum: ['aaa', 'bbb', 'ccc'],
default: 'aaa',
ui: {
widget,
change: jasmine.createSpy(),
} as SFAutoCompleteWidgetSchema,
},
},
};
page.newSchema(s);
const selectWidget = page.getWidget<AutoCompleteWidget>('sf-' + widget);
selectWidget.updateValue({ nzLabel: 'aaa', nzValue: { value: 'aaa', label: 'aaa' } } as any);
const item = s.properties!.a.ui as SFAutoCompleteWidgetSchema;
expect(item.change).toHaveBeenCalled();
});

describe('[data source]', () => {
it('with enum', fakeAsync(() => {
const data = ['aaa', 'bbb', 'ccc'];
Expand Down
15 changes: 13 additions & 2 deletions packages/form/src/widgets/autocomplete/autocomplete.widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,19 @@ export class AutoCompleteWidget extends ControlUIWidget<SFAutoCompleteWidgetSche

updateValue(item: NzAutocompleteOptionComponent) {
this.typing = item.nzLabel!;
this.setValue(item.nzValue);
if (this.ui.change) this.ui.change(item);
const data: SFSchemaEnum = item.nzValue;
this.setValue(data.value);
if (this.ui.change) {
this.ui.change(item, data);
}
}

_setValue(item: SFSchemaEnum): void {
let val = item.toString();
if (typeof item !== 'string') {
val = item.value;
}
this.setValue(val);
}

afterViewInit(): void {
Expand Down
20 changes: 16 additions & 4 deletions packages/form/src/widgets/autocomplete/demo/simple.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Simplest of usage.

```ts
import { Component } from '@angular/core';
import { SFSchema, SFAutoCompleteWidgetSchema } from '@delon/form';
import { SFAutoCompleteWidgetSchema, SFSchema } from '@delon/form';
import { NzMessageService } from 'ng-zorro-antd/message';
import { of } from 'rxjs';

Expand Down Expand Up @@ -45,12 +45,24 @@ export class DemoComponent {
ui: {
widget: 'autocomplete',
debounceTime: 100,
asyncData: (input: string) => of(input ? [{ label: input, value: 1 }, { label: input + input, value: 2 }] : []),
asyncData: input =>
of(
input
? [
{ label: input, value: 1, otherData: 1 },
{ label: input + input, value: 2 },
]
: [],
),
change: (comp, data) => console.log(comp, data),
} as SFAutoCompleteWidgetSchema,
default: 'asdf',
},
},
};
constructor(public msg: NzMessageService) { }
submit(value: any) { this.msg.success(JSON.stringify(value)); }
constructor(public msg: NzMessageService) {}
submit(value: any) {
this.msg.success(JSON.stringify(value));
}
}
```
2 changes: 1 addition & 1 deletion packages/form/src/widgets/autocomplete/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,5 @@ Every filter after data got is filtered by `filterOption`, data source is from `
| `[debounceTime]` | debounce time, minimum is `50` by default when it's realtime data source, unit: millisecond | `number` | `0` |
| `[defaultActiveFirstOption]` | Whether active the first item by default | `boolean` | `true` |
| `[backfill]` | Fill selected value into input when keyboard selection options is used | `boolean` | `false` |
| `[change]` | Change callback | `(item: NzAutocompleteOptionComponent) => void` | - |
| `[nzWidth]` | Customize width, unit is px | `number` | Trigger width of element |
| `[change]` | Change callback | `(item: NzAutocompleteOptionComponent, orgData: SFSchemaEnum) => void` | - |
2 changes: 1 addition & 1 deletion packages/form/src/widgets/autocomplete/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,5 @@ type: Widgets
| `[debounceTime]` | 去抖时间,当实时数据源时默认最少 `50`,单位:毫秒 | `number` | `0` |
| `[defaultActiveFirstOption]` | 是否默认高亮第一个选项 | `boolean` | `true` |
| `[backfill]` | 使用键盘选择选项的时候把选中项回填到输入框中 | `boolean` | `false` |
| `[change]` | 变更回调 | `(item: NzAutocompleteOptionComponent) => void` | - |
| `[nzWidth]` | 自定义宽度单位 px | `number` | 触发元素宽度 |
| `[change]` | 变更回调 | `(item: NzAutocompleteOptionComponent, orgData: SFSchemaEnum) => void` | - |
2 changes: 1 addition & 1 deletion packages/form/src/widgets/autocomplete/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@ export interface SFAutoCompleteWidgetSchema extends SFUISchemaItem {
/**
* 变更回调
*/
change?: (item: NzAutocompleteOptionComponent) => void;
change?: (item: NzAutocompleteOptionComponent, orgData: SFSchemaEnum) => void;
}
5 changes: 3 additions & 2 deletions packages/form/src/widgets/select/demo/simple.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Simplest of usage.

```ts
import { Component, ViewChild } from '@angular/core';
import { SFSchema, SFSelectWidgetSchema, SFComponent } from '@delon/form';
import { SFComponent, SFSchema, SFSelectWidgetSchema } from '@delon/form';
import { NzMessageService } from 'ng-zorro-antd/message';
import { of } from 'rxjs';
import { delay } from 'rxjs/operators';
Expand All @@ -35,13 +35,14 @@ export class DemoComponent {
type: 'string',
title: '状态',
enum: [
{ label: '待支付', value: 'WAIT_BUYER_PAY' },
{ label: '待支付', value: 'WAIT_BUYER_PAY', otherData: 1 },
{ label: '已支付', value: 'TRADE_SUCCESS' },
{ label: '交易完成', value: 'TRADE_FINISHED' },
],
default: 'WAIT_BUYER_PAY',
ui: {
widget: 'select',
change: (value, orgData) => console.log(value, orgData),
} as SFSelectWidgetSchema,
},
// 标签
Expand Down
2 changes: 1 addition & 1 deletion packages/form/src/widgets/select/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ Select.
| `[onSearch]` | Callback when search content is changed, parameter is search content, must return `Promise` object | `(text: string) => Promise<SFSchemaEnum[]>` | - |
| `[tokenSeparators]` | Separator for automatic word segmentation when it is tags and multiple mode | `string[]` | `[]` |
| `[maxTagCount]` | Maximum count of tag | `number` | - |
| `[change]` | Callback function when selected nz-option is changed | `(ngModel:any丨any[])=>void` | - |
| `[change]` | Callback function when selected nz-option is changed | `(ngModel:any丨any[], orgData: SFSchemaEnum丨SFSchemaEnum[])=>void` | - |
| `[openChange]` | Callback function when dropdown list is open or closed | `(status: boolean) => void` | - |
| `[scrollToBottom]` | Callback function when dropdown list is scrolled to bottom, can be used to trigger dynamic load | `() => void` | - |
2 changes: 1 addition & 1 deletion packages/form/src/widgets/select/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type: Widgets
| `[onSearch]` | 搜索内容变化回调函数,参数为搜索内容,必须返回 `Promise` 对象 | `(text: string) => Promise<SFSchemaEnum[]>` | - |
| `[tokenSeparators]` | 在 tags 和 multiple 模式下自动分词的分隔符 | `string[]` | `[]` |
| `[maxTagCount]` | 最多显示多少个 tag | `number` | - |
| `[change]` | 选中的 nz-option 发生变化时,调用此函数 | `(ngModel:any丨any[])=>void` | - |
| `[change]` | 选中的 nz-option 发生变化时,调用此函数 | `(ngModel:any丨any[], orgData: SFSchemaEnum丨SFSchemaEnum[])=>void` | - |
| `[openChange]` | 下拉菜单打开关闭回调函数 | `(status: boolean) => void` | - |
| `[scrollToBottom]` | 下拉菜单滚动到底部回调,可用于作为动态加载的触发条件 | `() => void` | - |
| `[customTemplate]` | 自定义选择框的Template内容 | `TemplateRef<{ $implicit: NzOptionComponent }>` | - |
Expand Down
2 changes: 1 addition & 1 deletion packages/form/src/widgets/select/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export interface SFSelectWidgetSchema extends SFUISchemaItem {
/**
* 选中的 `nz-option` 发生变化时,调用此函数
*/
change?: (ngModel: SFValue | SFValue[]) => void;
change?: (ngModel: SFValue | SFValue[], orgData: SFSchemaEnum | SFSchemaEnum[]) => void;

/**
* 下拉菜单打开关闭回调函数
Expand Down
96 changes: 64 additions & 32 deletions packages/form/src/widgets/select/select.widget.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ComponentFixture, fakeAsync } from '@angular/core/testing';
import { createTestContext } from '@delon/testing';
import { configureSFTestSuite, SFPage, TestFormComponent } from '../../../spec/base.spec';
import { SFSchema } from '../../../src/schema/index';
import { SFSelectWidgetSchema } from './schema';
import { SelectWidget } from './select.widget';

describe('form: widget: select', () => {
Expand Down Expand Up @@ -58,40 +59,71 @@ describe('form: widget: select', () => {
page.newSchema(s).typeEvent('click', 'nz-select').checkCount('.ant-select-disabled', 1).asyncEnd();
}));

xit('#events', fakeAsync(() => {
const s: SFSchema = {
properties: {
a: {
type: 'string',
title: '状态',
enum: [
{ label: '待支付', value: 'WAIT_BUYER_PAY' },
{ label: '已支付', value: 'TRADE_SUCCESS' },
{ label: '交易完成', value: 'TRADE_FINISHED' },
],
default: 'WAIT_BUYER_PAY',
ui: {
widget,
change: jasmine.createSpy(),
openChange: jasmine.createSpy(),
onSearch: jasmine.createSpy().and.returnValue(Promise.resolve()),
scrollToBottom: jasmine.createSpy(),
describe('#events', () => {
it('#change', fakeAsync(() => {
const s: SFSchema = {
properties: {
a: {
type: 'string',
title: '状态',
enum: [
{ label: '待支付', value: 'WAIT_BUYER_PAY' },
{ label: '已支付', value: 'TRADE_SUCCESS' },
{ label: '交易完成', value: 'TRADE_FINISHED' },
],
default: 'WAIT_BUYER_PAY',
ui: {
widget,
change: jasmine.createSpy(),
openChange: jasmine.createSpy(),
onSearch: jasmine.createSpy().and.returnValue(Promise.resolve()),
scrollToBottom: jasmine.createSpy(),
},
},
},
},
};
page.newSchema(s).typeEvent('click', 'nz-select-top-control').time(1000).dc();
const el = document.querySelector('.ant-select-dropdown-menu-item:not(.ant-select-dropdown-menu-item-selected)') as HTMLElement;
el.click();
page.dc().checkValue('/a', 'TRADE_SUCCESS').asyncEnd();
const item = s.properties!.a.ui as any;
expect(item.change).toHaveBeenCalled();
expect(item.openChange).toHaveBeenCalled();
getWidget().scrollToBottom();
expect(item.scrollToBottom).toHaveBeenCalled();
getWidget().searchChange('a');
expect(item.onSearch).toHaveBeenCalled();
}));
};
page.newSchema(s);
const selectWidget = getWidget();
selectWidget.change('WAIT_BUYER_PAY');
const item = s.properties!.a.ui as SFSelectWidgetSchema;
expect(item.change).toHaveBeenCalled();
selectWidget.openChange(true);
expect(item.openChange).toHaveBeenCalled();
selectWidget.scrollToBottom();
expect(item.scrollToBottom).toHaveBeenCalled();
selectWidget.searchChange('1');
expect(item.onSearch).toHaveBeenCalled();
}));
it('#change, when values is multiple', fakeAsync(() => {
const s: SFSchema = {
properties: {
a: {
type: 'string',
title: '状态',
enum: [
{
label: '待支付',
group: true,
children: [
{ label: '已支付', value: 'TRADE_SUCCESS' },
{ label: '交易完成', value: 'TRADE_FINISHED' },
],
},
],
ui: {
widget,
change: jasmine.createSpy(),
},
},
},
};
page.newSchema(s);
const selectWidget = getWidget();
selectWidget.change(['TRADE_FINISHED', 'TRADE_SUCCESS']);
const item = s.properties!.a.ui as SFSelectWidgetSchema;
expect(item.change).toHaveBeenCalled();
}));
});

it('should be clean value by click icon', fakeAsync(() => {
const s: SFSchema = {
Expand Down
15 changes: 14 additions & 1 deletion packages/form/src/widgets/select/select.widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,24 @@ export class SelectWidget extends ControlUIWidget<SFSelectWidgetSchema> implemen

change(values: SFValue) {
if (this.ui.change) {
this.ui.change(values);
this.ui.change(values, this.getOrgData(values));
}
this.setValue(values == null ? undefined : values);
}

private getOrgData(values: SFValue): SFSchemaEnum | SFSchemaEnum[] {
if (!Array.isArray(values)) {
return this.data.find(w => w.value === values)!;
}
return values.map(value => {
let item: SFSchemaEnum | null = null;
this.data.forEach(list => {
item = list.children?.find(w => w.value === value)!;
});
return item;
});
}

openChange(status: boolean) {
if (this.ui.openChange) {
this.ui.openChange(status);
Expand Down
Loading

0 comments on commit 7d70629

Please sign in to comment.