diff --git a/package.json b/package.json
index 1be19615c4..7253472028 100644
--- a/package.json
+++ b/package.json
@@ -87,11 +87,12 @@
"qrious": "^4.0.2",
"@webcomponents/custom-elements": "^1.6.0",
"aos": "^3.0.0-beta.6",
- "@ng-util/monaco-editor": "^16.0.0",
+ "@ng-util/monaco-editor": "^16.0.1",
"@nguniversal/express-engine": "^16.2.0",
"express": "^4.18.2",
"isutf8": "^4.0.0",
- "@github/hotkey": "^2.0.1"
+ "@github/hotkey": "^2.0.1",
+ "ng-antd-color-picker": "^0.0.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "^16.2.0",
diff --git a/packages/form/docs/customize.en-US.md b/packages/form/docs/customize.en-US.md
index a93e13f1fe..cfa3b06745 100644
--- a/packages/form/docs/customize.en-US.md
+++ b/packages/form/docs/customize.en-US.md
@@ -6,7 +6,7 @@ type: Documents
## Foreword
-`@delon/form` try our best to meet the needs of different environments, in addition to the built-in basic component widgets, you can further expand the requirements in two ways:
+`@delon/form` try our best to meet the needs of different environments, in addition to the built-in basic widgets (Some require manual registration), you can further expand the requirements in two ways:
## Custom widget in sf
@@ -18,15 +18,6 @@ Making a set of widgets for project can lead to faster development work.
### How to making widget
-**Third-party library**
-
-By default `@delon/form` implements some common third-party library widgets, which are called third-party component widgets. This widget exists in [widgets-third](https://github.com/ng-alain /delon/tree/master/packages/form/widgets-third) directory; you can use directly.
-
-| Name | Description | Document | Source |
-| ---- | ----------- | -------- | ------ |
-| `markdown` | Markdown Editor | [Document](/form/markdown) | [Source](https://github.com/ng-alain/delon/tree/master/packages/form/widgets-third/markdown) |
-| `tinymce` | Tinymce Editor | [Document](/form/tinymce) | [Source](https://github.com/ng-alain/delon/tree/master/packages/form/widgets-third/tinymce) |
-
**Create widgets**
A widget is a component. You only need to inherit `ControlWidget` to create a widget. For example:
diff --git a/packages/form/docs/customize.zh-CN.md b/packages/form/docs/customize.zh-CN.md
index 774b03ea0d..b692257d12 100644
--- a/packages/form/docs/customize.zh-CN.md
+++ b/packages/form/docs/customize.zh-CN.md
@@ -6,7 +6,7 @@ type: Documents
## 写在前面
-`@delon/form` 尽可能满足不同需求,除现有内置的十几种基础组件小部件外,可以通过以下两种方式进一步扩展需求:
+`@delon/form` 尽可能满足不同需求,除现有内置的十几种基础小部件(部分需要手动注册)外,可以通过以下两种方式进一步扩展需求:
## 自定义小部件
@@ -18,17 +18,6 @@ type: Documents
### 编写小部件
-**常见小部件库**
-
-默认情况下 @delon/form 实现了一些常见需求,但需要额外类库支持的,称它为第三方组件小部件,这一部分小部件存在于[widgets-third](https://github.com/ng-alain/delon/tree/master/packages/form/widgets-third)目录里;你可以直接复制使用。
-
-这些组件包括:
-
-| 名称 | 描述 | 文档 | 源代码 |
-| --- | ---- | ---- | ---- |
-| `markdown` | Markdown 编辑器 | [文档](/form/markdown) | [源代码](https://github.com/ng-alain/delon/tree/master/packages/form/widgets-third/markdown) |
-| `tinymce` | Tinymce 富文本框 | [文档](/form/tinymce) | [源代码](https://github.com/ng-alain/delon/tree/master/packages/form/widgets-third/tinymce) |
-
**自己创建小部件**
小部件就是一个组件,你只需要继承 `ControlWidget` 就相当于构建一个小部件,其结构如下:
diff --git a/packages/form/spec/base.spec.ts b/packages/form/spec/base.spec.ts
index 17e3b67dd2..4067751453 100644
--- a/packages/form/spec/base.spec.ts
+++ b/packages/form/spec/base.spec.ts
@@ -75,10 +75,16 @@ export function builder(options?: {
};
}
-export function configureSFTestSuite(): void {
+export function configureSFTestSuite(options?: { imports?: NzSafeAny[] }): void {
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [NoopAnimationsModule, AlainThemeModule.forRoot(), DelonFormModule.forRoot(), HttpClientTestingModule],
+ imports: [
+ NoopAnimationsModule,
+ AlainThemeModule.forRoot(),
+ DelonFormModule.forRoot(),
+ HttpClientTestingModule,
+ ...(options?.imports ?? [])
+ ],
declarations: [TestFormComponent]
});
});
diff --git a/packages/form/src/module.ts b/packages/form/src/module.ts
index b72cad44af..e67ba6a9cf 100644
--- a/packages/form/src/module.ts
+++ b/packages/form/src/module.ts
@@ -3,10 +3,8 @@ import { CommonModule } from '@angular/common';
import { ModuleWithProviders, NgModule, NgZone } from '@angular/core';
import { FormsModule } from '@angular/forms';
-import { NzAutocompleteModule } from 'ng-zorro-antd/auto-complete';
import { NzButtonModule } from 'ng-zorro-antd/button';
import { NzCardModule } from 'ng-zorro-antd/card';
-import { NzCascaderModule } from 'ng-zorro-antd/cascader';
import { NzCheckboxModule } from 'ng-zorro-antd/checkbox';
import { NzDatePickerModule } from 'ng-zorro-antd/date-picker';
import { NzFormModule } from 'ng-zorro-antd/form';
@@ -14,28 +12,18 @@ import { NzGridModule } from 'ng-zorro-antd/grid';
import { NzIconModule } from 'ng-zorro-antd/icon';
import { NzInputModule } from 'ng-zorro-antd/input';
import { NzInputNumberModule } from 'ng-zorro-antd/input-number';
-import { NzMentionModule } from 'ng-zorro-antd/mention';
import { NzModalModule } from 'ng-zorro-antd/modal';
import { NzRadioModule } from 'ng-zorro-antd/radio';
-import { NzRateModule } from 'ng-zorro-antd/rate';
import { NzSelectModule } from 'ng-zorro-antd/select';
-import { NzSliderModule } from 'ng-zorro-antd/slider';
import { NzSwitchModule } from 'ng-zorro-antd/switch';
-import { NzTagModule } from 'ng-zorro-antd/tag';
-import { NzTimePickerModule } from 'ng-zorro-antd/time-picker';
import { NzToolTipModule } from 'ng-zorro-antd/tooltip';
-import { NzTransferModule } from 'ng-zorro-antd/transfer';
-import { NzTreeSelectModule } from 'ng-zorro-antd/tree-select';
-import { NzUploadModule } from 'ng-zorro-antd/upload';
import { DelonLocaleModule } from '@delon/theme';
import { AlainConfigService } from '@delon/util/config';
const ZORROS = [
- NzAutocompleteModule,
NzButtonModule,
NzCardModule,
- NzCascaderModule,
NzCheckboxModule,
NzDatePickerModule,
NzFormModule,
@@ -43,19 +31,11 @@ const ZORROS = [
NzIconModule,
NzInputModule,
NzInputNumberModule,
- NzMentionModule,
NzModalModule,
NzRadioModule,
- NzRateModule,
NzSelectModule,
- NzSliderModule,
NzSwitchModule,
- NzTagModule,
- NzTimePickerModule,
- NzToolTipModule,
- NzTransferModule,
- NzTreeSelectModule,
- NzUploadModule
+ NzToolTipModule
];
import { SFFixedDirective } from './sf-fixed.directive';
@@ -71,28 +51,18 @@ const COMPONENTS = [SFComponent, SFItemComponent, SFItemWrapComponent, SFTemplat
import { WidgetRegistry } from './widget.factory';
import { ArrayWidget } from './widgets/array/array.widget';
-import { AutoCompleteWidget } from './widgets/autocomplete/autocomplete.widget';
import { BooleanWidget } from './widgets/boolean/boolean.widget';
-import { CascaderWidget } from './widgets/cascader/cascader.widget';
import { CheckboxWidget } from './widgets/checkbox/checkbox.widget';
import { CustomWidget } from './widgets/custom/custom.widget';
import { DateWidget } from './widgets/date/date.widget';
-import { MentionWidget } from './widgets/mention/mention.widget';
import { NumberWidget } from './widgets/number/number.widget';
import { NzWidgetRegistry } from './widgets/nz-widget.registry';
import { ObjectWidget } from './widgets/object/object.widget';
import { RadioWidget } from './widgets/radio/radio.widget';
-import { RateWidget } from './widgets/rate/rate.widget';
import { SelectWidget } from './widgets/select/select.widget';
-import { SliderWidget } from './widgets/slider/slider.widget';
import { StringWidget } from './widgets/string/string.widget';
-import { TagWidget } from './widgets/tag/tag.widget';
import { TextWidget } from './widgets/text/text.widget';
import { TextareaWidget } from './widgets/textarea/textarea.widget';
-import { TimeWidget } from './widgets/time/time.widget';
-import { TransferWidget } from './widgets/transfer/transfer.widget';
-import { TreeSelectWidget } from './widgets/tree-select/tree-select.widget';
-import { UploadWidget } from './widgets/upload/upload.widget';
const WIDGETS = [
ObjectWidget,
@@ -100,21 +70,11 @@ const WIDGETS = [
StringWidget,
NumberWidget,
DateWidget,
- TimeWidget,
RadioWidget,
CheckboxWidget,
BooleanWidget,
TextareaWidget,
SelectWidget,
- TreeSelectWidget,
- TagWidget,
- UploadWidget,
- TransferWidget,
- SliderWidget,
- RateWidget,
- AutoCompleteWidget,
- CascaderWidget,
- MentionWidget,
CustomWidget,
TextWidget
];
diff --git a/packages/form/src/widgets/array/index.en-US.md b/packages/form/src/widgets/array/index.en-US.md
index 88566b5423..1129dadd3d 100644
--- a/packages/form/src/widgets/array/index.en-US.md
+++ b/packages/form/src/widgets/array/index.en-US.md
@@ -2,6 +2,7 @@
title: array
subtitle: Array
type: Widgets
+order: 2
---
Create array object, it's only valid when `schema.type="array"`.
diff --git a/packages/form/src/widgets/array/index.zh-CN.md b/packages/form/src/widgets/array/index.zh-CN.md
index fd179a3a5d..f8e4f8d5b9 100644
--- a/packages/form/src/widgets/array/index.zh-CN.md
+++ b/packages/form/src/widgets/array/index.zh-CN.md
@@ -2,6 +2,7 @@
title: array
subtitle: 数组
type: Widgets
+order: 2
---
创建对象数组,只对 `schema.type="array"` 时有效。
diff --git a/packages/form/src/widgets/autocomplete/autocomplete.widget.html b/packages/form/src/widgets/autocomplete/autocomplete.widget.html
deleted file mode 100644
index 128281dcd5..0000000000
--- a/packages/form/src/widgets/autocomplete/autocomplete.widget.html
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
- {{ i.label }}
-
-
diff --git a/packages/form/src/widgets/boolean/index.en-US.md b/packages/form/src/widgets/boolean/index.en-US.md
index e229751769..821870a325 100644
--- a/packages/form/src/widgets/boolean/index.en-US.md
+++ b/packages/form/src/widgets/boolean/index.en-US.md
@@ -2,6 +2,7 @@
title: boolean
subtitle: Switch
type: Widgets
+order: 4
---
Switching Selector.
diff --git a/packages/form/src/widgets/boolean/index.zh-CN.md b/packages/form/src/widgets/boolean/index.zh-CN.md
index 50b568ae47..81488a03e2 100644
--- a/packages/form/src/widgets/boolean/index.zh-CN.md
+++ b/packages/form/src/widgets/boolean/index.zh-CN.md
@@ -2,6 +2,7 @@
title: boolean
subtitle: 开关
type: Widgets
+order: 4
---
开关选择器
diff --git a/packages/form/src/widgets/cascader/cascader.widget.html b/packages/form/src/widgets/cascader/cascader.widget.html
deleted file mode 100644
index 25fee31981..0000000000
--- a/packages/form/src/widgets/cascader/cascader.widget.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
diff --git a/packages/form/src/widgets/checkbox/demo/simple.md b/packages/form/src/widgets/checkbox/demo/simple.md
index 62ff8d36e9..5a59a916b5 100644
--- a/packages/form/src/widgets/checkbox/demo/simple.md
+++ b/packages/form/src/widgets/checkbox/demo/simple.md
@@ -15,7 +15,8 @@ Simplest of usage.
```ts
import { Component } from '@angular/core';
-import { SFCascaderWidgetSchema, SFCheckboxWidgetSchema, SFSchema } from '@delon/form';
+import { SFCheckboxWidgetSchema, SFSchema } from '@delon/form';
+import type { SFCascaderWidgetSchema } from '@delon/form/widgets/cascader';
import { NzMessageService } from 'ng-zorro-antd/message';
import { of, delay } from 'rxjs';
diff --git a/packages/form/src/widgets/custom/demo/simple.md b/packages/form/src/widgets/custom/demo/simple.md
index 697e520476..b31a7a19cf 100644
--- a/packages/form/src/widgets/custom/demo/simple.md
+++ b/packages/form/src/widgets/custom/demo/simple.md
@@ -42,7 +42,7 @@ import { NzMessageService } from 'ng-zorro-antd/message';
-
+
`
diff --git a/packages/form/src/widgets/index.ts b/packages/form/src/widgets/index.ts
index 7c15132d9d..7045bcf234 100644
--- a/packages/form/src/widgets/index.ts
+++ b/packages/form/src/widgets/index.ts
@@ -8,36 +8,15 @@ export * from './number/number.widget';
export * from './number/schema';
export * from './date/date.widget';
export * from './date/schema';
-export * from './time/time.widget';
-export * from './time/schema';
export * from './radio/radio.widget';
export * from './radio/schema';
export * from './checkbox/checkbox.widget';
export * from './checkbox/schema';
export * from './boolean/boolean.widget';
-export * from './cascader/schema';
export * from './textarea/textarea.widget';
export * from './textarea/schema';
export * from './select/select.widget';
export * from './select/schema';
-export * from './tree-select/tree-select.widget';
-export * from './tree-select/schema';
-export * from './tag/tag.widget';
-export * from './tag/schema';
-export * from './upload/upload.widget';
-export * from './upload/schema';
-export * from './transfer/transfer.widget';
-export * from './transfer/schema';
-export * from './slider/slider.widget';
-export * from './slider/schema';
-export * from './rate/rate.widget';
-export * from './rate/schema';
-export * from './autocomplete/autocomplete.widget';
-export * from './autocomplete/schema';
-export * from './cascader/cascader.widget';
-export * from './cascader/schema';
-export * from './mention/mention.widget';
-export * from './mention/schema';
export * from './text/text.widget';
export * from './text/schema';
export * from './custom/custom.widget';
diff --git a/packages/form/src/widgets/mention/mention.widget.html b/packages/form/src/widgets/mention/mention.widget.html
deleted file mode 100644
index 90c3c5bc23..0000000000
--- a/packages/form/src/widgets/mention/mention.widget.html
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
diff --git a/packages/form/src/widgets/number/index.en-US.md b/packages/form/src/widgets/number/index.en-US.md
index 60e7e01167..3add327866 100644
--- a/packages/form/src/widgets/number/index.en-US.md
+++ b/packages/form/src/widgets/number/index.en-US.md
@@ -2,6 +2,7 @@
title: number
subtitle: Input Number
type: Widgets
+order: 5
---
Enter a number within certain range with the mouse or keyboard.
diff --git a/packages/form/src/widgets/number/index.zh-CN.md b/packages/form/src/widgets/number/index.zh-CN.md
index 403e85c6f4..183f3ccc20 100644
--- a/packages/form/src/widgets/number/index.zh-CN.md
+++ b/packages/form/src/widgets/number/index.zh-CN.md
@@ -2,6 +2,7 @@
title: number
subtitle: 数字
type: Widgets
+order: 5
---
通过鼠标或键盘,输入范围内的数值
diff --git a/packages/form/src/widgets/nz-widget.registry.ts b/packages/form/src/widgets/nz-widget.registry.ts
index 0898894504..910a00de41 100644
--- a/packages/form/src/widgets/nz-widget.registry.ts
+++ b/packages/form/src/widgets/nz-widget.registry.ts
@@ -1,25 +1,15 @@
import { ArrayWidget } from './array/array.widget';
-import { AutoCompleteWidget } from './autocomplete/autocomplete.widget';
import { BooleanWidget } from './boolean/boolean.widget';
-import { CascaderWidget } from './cascader/cascader.widget';
import { CheckboxWidget } from './checkbox/checkbox.widget';
import { CustomWidget } from './custom/custom.widget';
import { DateWidget } from './date/date.widget';
-import { MentionWidget } from './mention/mention.widget';
import { NumberWidget } from './number/number.widget';
import { ObjectWidget } from './object/object.widget';
import { RadioWidget } from './radio/radio.widget';
-import { RateWidget } from './rate/rate.widget';
import { SelectWidget } from './select/select.widget';
-import { SliderWidget } from './slider/slider.widget';
import { StringWidget } from './string/string.widget';
-import { TagWidget } from './tag/tag.widget';
import { TextWidget } from './text/text.widget';
import { TextareaWidget } from './textarea/textarea.widget';
-import { TimeWidget } from './time/time.widget';
-import { TransferWidget } from './transfer/transfer.widget';
-import { TreeSelectWidget } from './tree-select/tree-select.widget';
-import { UploadWidget } from './upload/upload.widget';
import { WidgetRegistry } from '../widget.factory';
export class NzWidgetRegistry extends WidgetRegistry {
@@ -34,21 +24,11 @@ export class NzWidgetRegistry extends WidgetRegistry {
this.register('number', NumberWidget);
this.register('integer', NumberWidget);
this.register('date', DateWidget);
- this.register('time', TimeWidget);
this.register('radio', RadioWidget);
this.register('checkbox', CheckboxWidget);
this.register('boolean', BooleanWidget);
this.register('textarea', TextareaWidget);
this.register('select', SelectWidget);
- this.register('tree-select', TreeSelectWidget);
- this.register('tag', TagWidget);
- this.register('upload', UploadWidget);
- this.register('transfer', TransferWidget);
- this.register('slider', SliderWidget);
- this.register('rate', RateWidget);
- this.register('autocomplete', AutoCompleteWidget);
- this.register('cascader', CascaderWidget);
- this.register('mention', MentionWidget);
this.register('custom', CustomWidget);
this.setDefault(StringWidget);
diff --git a/packages/form/src/widgets/object/index.en-US.md b/packages/form/src/widgets/object/index.en-US.md
index 03b9344dcd..ef537b2f88 100644
--- a/packages/form/src/widgets/object/index.en-US.md
+++ b/packages/form/src/widgets/object/index.en-US.md
@@ -2,6 +2,7 @@
title: object
subtitle: Object
type: Widgets
+order: 1
---
Create an object widget, valid only for `schema.type="object"`.
diff --git a/packages/form/src/widgets/object/index.zh-CN.md b/packages/form/src/widgets/object/index.zh-CN.md
index d94157f777..56739e0259 100644
--- a/packages/form/src/widgets/object/index.zh-CN.md
+++ b/packages/form/src/widgets/object/index.zh-CN.md
@@ -2,6 +2,7 @@
title: object
subtitle: 对象
type: Widgets
+order: 1
---
创建对象,只对 `schema.type="object"` 时有效。
diff --git a/packages/form/src/widgets/rate/rate.widget.html b/packages/form/src/widgets/rate/rate.widget.html
deleted file mode 100644
index a7c5e18e1d..0000000000
--- a/packages/form/src/widgets/rate/rate.widget.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
- {{ text }}
-
diff --git a/packages/form/src/widgets/select/index.en-US.md b/packages/form/src/widgets/select/index.en-US.md
index 86eb1046f3..1e47676607 100644
--- a/packages/form/src/widgets/select/index.en-US.md
+++ b/packages/form/src/widgets/select/index.en-US.md
@@ -2,6 +2,7 @@
title: select
subtitle: Select
type: Widgets
+order: 6
---
Select.
diff --git a/packages/form/src/widgets/select/index.zh-CN.md b/packages/form/src/widgets/select/index.zh-CN.md
index 063c0db520..79b45db6f9 100644
--- a/packages/form/src/widgets/select/index.zh-CN.md
+++ b/packages/form/src/widgets/select/index.zh-CN.md
@@ -2,6 +2,7 @@
title: select
subtitle: 选择器
type: Widgets
+order: 6
---
下拉选择器。
diff --git a/packages/form/src/widgets/slider/slider.widget.html b/packages/form/src/widgets/slider/slider.widget.html
deleted file mode 100644
index 5ec0c26c41..0000000000
--- a/packages/form/src/widgets/slider/slider.widget.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
diff --git a/packages/form/src/widgets/string/index.en-US.md b/packages/form/src/widgets/string/index.en-US.md
index 0e5c69a03e..c6b191c6ef 100644
--- a/packages/form/src/widgets/string/index.en-US.md
+++ b/packages/form/src/widgets/string/index.en-US.md
@@ -2,6 +2,7 @@
title: string
subtitle: Input
type: Widgets
+order: 3
---
Default widget, A basic widget for getting the user input is a text field.
diff --git a/packages/form/src/widgets/string/index.zh-CN.md b/packages/form/src/widgets/string/index.zh-CN.md
index f68672367b..7767ec6ecf 100644
--- a/packages/form/src/widgets/string/index.zh-CN.md
+++ b/packages/form/src/widgets/string/index.zh-CN.md
@@ -2,6 +2,7 @@
title: string
subtitle: 文本框
type: Widgets
+order: 3
---
默认小部件,一般用于字符串元素。
diff --git a/packages/form/src/widgets/tag/tag.widget.html b/packages/form/src/widgets/tag/tag.widget.html
deleted file mode 100644
index feb5e91a6b..0000000000
--- a/packages/form/src/widgets/tag/tag.widget.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
- {{ i.label }}
-
-
-
-
-
diff --git a/packages/form/src/widgets/tag/tag.widget.ts b/packages/form/src/widgets/tag/tag.widget.ts
deleted file mode 100644
index 52a0e81aa0..0000000000
--- a/packages/form/src/widgets/tag/tag.widget.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import { Component, ViewEncapsulation } from '@angular/core';
-
-import { SFTagWidgetSchema } from './schema';
-import { SFValue } from '../../interface';
-import { SFSchemaEnum } from '../../schema';
-import { getData } from '../../utils';
-import { ControlUIWidget } from '../../widget';
-
-@Component({
- selector: 'sf-tag',
- templateUrl: './tag.widget.html',
- preserveWhitespaces: false,
- encapsulation: ViewEncapsulation.None
-})
-export class TagWidget extends ControlUIWidget {
- data: SFSchemaEnum[] = [];
-
- reset(value: SFValue): void {
- getData(this.schema, this.ui, value).subscribe(list => {
- this.data = list;
- this.detectChanges();
- });
- }
-
- onChange(item: SFSchemaEnum): void {
- item.checked = !item.checked;
- this.updateValue();
- if (this.ui.checkedChange) {
- this.ui.checkedChange(item.checked);
- }
- }
-
- _close(e: MouseEvent): void {
- if (this.ui.onClose) this.ui.onClose(e);
- }
-
- private updateValue(): void {
- this.formProperty.setValue(
- this.data.filter(w => w.checked).map(i => i.value),
- false
- );
- }
-}
diff --git a/packages/form/src/widgets/time/time.widget.html b/packages/form/src/widgets/time/time.widget.html
deleted file mode 100644
index 0509498b46..0000000000
--- a/packages/form/src/widgets/time/time.widget.html
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
diff --git a/packages/form/src/widgets/transfer/transfer.widget.html b/packages/form/src/widgets/transfer/transfer.widget.html
deleted file mode 100644
index 766e55b115..0000000000
--- a/packages/form/src/widgets/transfer/transfer.widget.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
diff --git a/packages/form/src/widgets/tree-select/tree-select.widget.html b/packages/form/src/widgets/tree-select/tree-select.widget.html
deleted file mode 100644
index dbe3e76727..0000000000
--- a/packages/form/src/widgets/tree-select/tree-select.widget.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
diff --git a/packages/form/src/widgets/upload/upload.widget.html b/packages/form/src/widgets/upload/upload.widget.html
deleted file mode 100644
index 7c2fb28e2d..0000000000
--- a/packages/form/src/widgets/upload/upload.widget.html
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/packages/form/widgets-third/markdown/index.en-US.md b/packages/form/widgets-third/markdown/index.en-US.md
deleted file mode 100644
index bd8c40c7a5..0000000000
--- a/packages/form/widgets-third/markdown/index.en-US.md
+++ /dev/null
@@ -1,92 +0,0 @@
----
-title: markdown
-subtitle: Markdown Editor
-type: Third Widgets
----
-
-Markdown Editor
-
-> Note: third party widget is not registered by default, see details from [Customize Widgets](https://ng-alain.com/form/customize/en).
-
-## How to Use
-
-**Installation dependencies**
-
-Since the Markdown editor relies on a third-party plug-in [ngx-simplemde](https://github.com/cipchk/ngx-simplemde), the dependency should be installed first when using it
-
-`npm i -S ngx-simplemde`
-
-
-**Import module**
-
-- The project built using the latest scaffolding provides a third-party widget registration entry: `src/app/shared/json-schema/json-schema.module.ts`
-- `MarkdownWidget` needs to be declared in `JsonSchemaModule`
-
-```ts
-export const SCHEMA_THIRDS_COMPONENTS = [MarkdownWidget];
-
-@NgModule({
- declarations: SCHEMA_THIRDS_COMPONENTS,
- imports: [
- SharedModule,
- DelonFormModule.forRoot(),
- SimplemdeModule.forRoot({ style: 'default' }),
- ],
- exports: SCHEMA_THIRDS_COMPONENTS
-})
-export class JsonSchemaModule {
-}
-```
-
-**Widget registration**
-
-- Register the widget to the `WidgetRegistry` registry
-
-```ts
-export class JsonSchemaModule {
- constructor(widgetRegistry: WidgetRegistry) {
- widgetRegistry.register(MarkdownWidget.KEY, MarkdownWidget);
- }
-}
-```
-
-**Import resources**
-
-Import the corresponding resources in `angular.json`.
-
-```json
-"styles": [
- "src/styles.less"
-]
-"scripts": [
- "node_modules/simplemde-antd/dist/simplemde.min.js"
-]
-```
-
-**Import styles**
-
-After using `style.less` as the style entry, you need to import the style file of `ngx-simplemde` and define some custom variables
-
-```less
-// src/style.less
-@import 'ngx-simplemde/index.less';
-// Change existing parameters here:
-@simplemde-icon-url: '//at.alicdn.com/t/font_700857_mnodkd1cp9l766r';
-@simplemde-statusbar-lines: 'Lins:';
-@simplemde-statusbar-words: 'words:';
-@simplemde-statusbar-characters: '字符:';
-@simplemde-statusbar-counts: '字数:';
-```
-
-## Source Code
-
-[Source Code](https://github.com/ng-alain/delon/tree/master/packages/form/widgets-third/markdown).
-
-## API
-
-### ui
-
-| Property | Description | Type | Default |
-|----------|-------------|------|---------|
-| `[options]` | Configuration options, [official website](https://github.com/cipchk/ngx-simplemde) | `object` | - |
-| `[change]` | Callback function when content in editor is changed | `(md: string) => void` | - |
diff --git a/packages/form/widgets-third/markdown/index.zh-CN.md b/packages/form/widgets-third/markdown/index.zh-CN.md
deleted file mode 100644
index 3af542c09d..0000000000
--- a/packages/form/widgets-third/markdown/index.zh-CN.md
+++ /dev/null
@@ -1,91 +0,0 @@
----
-title: markdown
-subtitle: Markdown编辑器
-type: Third Widgets
----
-
-Markdown编辑器。
-
-> 注:第三方小部件默认并未注册,细节见[定制小部件](https://ng-alain.com/form/customize)。
-
-## 如何使用
-
-**安装依赖**
-
-由于Markdown编辑器依赖第三方插件[ngx-simplemde](https://github.com/cipchk/ngx-simplemde),所以使用时应首先安装依赖
-
-`npm i -S ngx-simplemde`
-
-**导入模块**
-
-- 使用最新脚手架搭建出的项目提供了第三方控件注册入口: `src/app/shared/json-schema/json-schema.module.ts`
-- 需将`MarkdownWidget`在`JsonSchemaModule`中进行声明
-
-```ts
-export const SCHEMA_THIRDS_COMPONENTS = [MarkdownWidget];
-
-@NgModule({
- declarations: SCHEMA_THIRDS_COMPONENTS,
- imports: [
- SharedModule,
- DelonFormModule.forRoot(),
- SimplemdeModule.forRoot({ style: 'default' }),
- ],
- exports: SCHEMA_THIRDS_COMPONENTS
-})
-export class JsonSchemaModule {
-}
-```
-
-**控件注册**
-
-- 将控件注册到`WidgetRegistry`注册表中
-
-```ts
-export class JsonSchemaModule {
- constructor(widgetRegistry: WidgetRegistry) {
- widgetRegistry.register(MarkdownWidget.KEY, MarkdownWidget);
- }
-}
-```
-
-**导入资源**
-
-在 `angular.json` 导入相应资源。
-
-```json
-"styles": [
- "src/styles.less"
-]
-"scripts": [
- "node_modules/simplemde-antd/dist/simplemde.min.js"
-]
-```
-
-**导入样式**
-
-使用`style.less`作为样式入口后,需将`ngx-simplemde`的样式文件导入进去,并定义一些自定义变量
-
-```less
-// src/style.less
-@import 'ngx-simplemde/index.less';
-// Change existing parameters here:
-@simplemde-icon-url: '//at.alicdn.com/t/font_700857_mnodkd1cp9l766r';
-@simplemde-statusbar-lines: 'Lins:';
-@simplemde-statusbar-words: 'words:';
-@simplemde-statusbar-characters: '字符:';
-@simplemde-statusbar-counts: '字数:';
-```
-
-## 源代码
-
-[源代码](https://github.com/ng-alain/delon/tree/master/packages/form/widgets-third/markdown)。
-
-## API
-
-### ui 属性
-
-| 成员 | 说明 | 类型 | 默认值 |
-|----|----|----|-----|
-| `[options]` | 配置项说明,[见官网](https://github.com/cipchk/ngx-simplemde) | `object` | - |
-| `[change]` | 编辑器内容发生改变时会触发该事件 | `(md: string) => void` | - |
diff --git a/packages/form/widgets-third/markdown/markdown.widget.ts b/packages/form/widgets-third/markdown/markdown.widget.ts
deleted file mode 100644
index e751dcdd8f..0000000000
--- a/packages/form/widgets-third/markdown/markdown.widget.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { Component } from '@angular/core';
-
-import { ControlWidget } from '@delon/form';
-
-@Component({
- selector: 'sf-md',
- template: `
-
-
-
- `
-})
-export class MarkdownWidget extends ControlWidget {
- static readonly KEY = 'md';
-
- _change(value: string): void {
- this.setValue(value);
- if (this.ui.change) this.ui.change(value);
- }
-}
diff --git a/packages/form/widgets-third/monaco-editor/demo/simple.md b/packages/form/widgets-third/monaco-editor/demo/simple.md
new file mode 100644
index 0000000000..c645d5f23a
--- /dev/null
+++ b/packages/form/widgets-third/monaco-editor/demo/simple.md
@@ -0,0 +1,48 @@
+---
+title:
+ zh-CN: 基础样例
+ en-US: Basic Usage
+order: 0
+---
+
+## zh-CN
+
+最简单的用法。
+
+## en-US
+
+Simplest of usage.
+
+```ts
+import { Component } from '@angular/core';
+
+import { SFSchema } from '@delon/form';
+import type { MonacoEditorWidgetSchema } from '@delon/form/widgets-third/monaco-editor';
+import { NzMessageService } from 'ng-zorro-antd/message';
+
+@Component({
+ selector: 'app-demo',
+ template: ``
+})
+export class DemoComponent {
+ schema: SFSchema = {
+ properties: {
+ json: {
+ type: 'string',
+ title: 'JSON',
+ default: `{"string": "abc","number": 1 }`,
+ ui: {
+ widget: 'monaco-editor',
+ options: { language: 'json' }
+ } as MonacoEditorWidgetSchema
+ }
+ }
+ };
+
+ constructor(private msg: NzMessageService) {}
+
+ submit(value: {}): void {
+ this.msg.success(JSON.stringify(value));
+ }
+}
+```
diff --git a/packages/form/widgets-third/monaco-editor/index.en-US.md b/packages/form/widgets-third/monaco-editor/index.en-US.md
new file mode 100644
index 0000000000..c634a84bce
--- /dev/null
+++ b/packages/form/widgets-third/monaco-editor/index.en-US.md
@@ -0,0 +1,33 @@
+---
+title: monaco-editor
+subtitle: Monaco Editor
+type: Third Widgets
+---
+
+Markdown Editor
+
+## How to Use
+
+**Installation dependencies**
+
+`yarn add @ng-util/monaco-editor`
+
+**Import module**
+
+- 1. Import `NuMonacoEditorModule.forRoot()` in `app.module.ts`
+- 2. Import `MonacoEditorWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
+
+> For more Monaco Editor configuration, please refer to [@ng-util/monaco-editor](https://github.com/ng-util/ng-util/blob/master/packages/monaco-editor/README.md#usage).
+
+## API
+
+### ui
+
+| Property | Description | Type | Default |
+|----------|-------------|------|---------|
+| `[options]` | Configuration options, [official website](https://microsoft.github.io/monaco-editor/docs.html) | `monaco.editor.IStandaloneEditorConstructionOptions` | - |
+| `[delay]` | Time of lazy loading | `number` | - |
+| `[change]` | Callback function when content in editor is changed | `(value: string) => void` | - |
+| `[height]` | Height of monaco editor | `string` | `200px` |
+| `[model]` | Model of monaco editor | `NuMonacoEditorModel` | - |
+| `(event)` | Event callback | `EventEmitter` | - |
diff --git a/packages/form/widgets-third/monaco-editor/index.ts b/packages/form/widgets-third/monaco-editor/index.ts
new file mode 100644
index 0000000000..ba3a3cf2dc
--- /dev/null
+++ b/packages/form/widgets-third/monaco-editor/index.ts
@@ -0,0 +1,21 @@
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { NuMonacoEditorModule } from '@ng-util/monaco-editor';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+
+import { MonacoEditorWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, DelonFormModule, NuMonacoEditorModule],
+ declarations: [MonacoEditorWidget]
+})
+export class MonacoEditorWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(MonacoEditorWidget.KEY, MonacoEditorWidget);
+ }
+}
diff --git a/packages/form/widgets-third/monaco-editor/index.zh-CN.md b/packages/form/widgets-third/monaco-editor/index.zh-CN.md
new file mode 100644
index 0000000000..1fa7cfbbc8
--- /dev/null
+++ b/packages/form/widgets-third/monaco-editor/index.zh-CN.md
@@ -0,0 +1,33 @@
+---
+title: monaco-editor
+subtitle: Monaco Editor
+type: Third Widgets
+---
+
+Markdown编辑器。
+
+## 如何使用
+
+**安装依赖**
+
+`yarn add @ng-util/monaco-editor`
+
+**导入模块**
+
+- 1、在 `app.module.ts` 下导入 `NuMonacoEditorModule.forRoot()`
+- 2、在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `MonacoEditorWidgetModule`。
+
+> 关于更多 Monaco Editor 配置请参考 [@ng-util/monaco-editor](https://github.com/ng-util/ng-util/blob/master/packages/monaco-editor/README.md#usage)。
+
+## API
+
+### ui 属性
+
+| 成员 | 说明 | 类型 | 默认值 |
+|----|----|----|-----|
+| `[options]` | 配置项说明,[见官网](https://microsoft.github.io/monaco-editor/docs.html) | `monaco.editor.IStandaloneEditorConstructionOptions` | - |
+| `[delay]` | 延迟加载时间 | `number` | - |
+| `[change]` | 编辑器内容发生改变时会触发该事件 | `(value: string) => void` | - |
+| `[height]` | Height of monaco editor | `string` | `200px` |
+| `[model]` | Model of monaco editor | `NuMonacoEditorModel` | - |
+| `(event)` | Event callback | `EventEmitter` | - |
diff --git a/packages/form/widgets-third/monaco-editor/ng-package.json b/packages/form/widgets-third/monaco-editor/ng-package.json
new file mode 100644
index 0000000000..7f578c054e
--- /dev/null
+++ b/packages/form/widgets-third/monaco-editor/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-third-monaco-editor",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/widgets-third/monaco-editor/schema.ts b/packages/form/widgets-third/monaco-editor/schema.ts
new file mode 100644
index 0000000000..87767d34bd
--- /dev/null
+++ b/packages/form/widgets-third/monaco-editor/schema.ts
@@ -0,0 +1,19 @@
+import type { NuMonacoEditorEvent, NuMonacoEditorModel } from '@ng-util/monaco-editor';
+
+import type { SFUISchemaItem } from '@delon/form';
+
+export interface MonacoEditorWidgetSchema extends SFUISchemaItem {
+ options?: monaco.editor.IStandaloneEditorConstructionOptions;
+ delay?: number;
+ change?: (value: string) => void;
+ model?: NuMonacoEditorModel;
+ /**
+ * Height of monaco editor, default: `200px`
+ */
+ height?: string;
+ /**
+ * Whether to automatically format the document
+ */
+ autoFormat?: boolean;
+ event?: (ev: NuMonacoEditorEvent) => void;
+}
diff --git a/packages/form/widgets-third/monaco-editor/widget.ts b/packages/form/widgets-third/monaco-editor/widget.ts
new file mode 100644
index 0000000000..354cf1a5d3
--- /dev/null
+++ b/packages/form/widgets-third/monaco-editor/widget.ts
@@ -0,0 +1,45 @@
+import { Component } from '@angular/core';
+
+import type { NuMonacoEditorEvent } from '@ng-util/monaco-editor';
+
+import { ControlUIWidget } from '@delon/form';
+
+import type { MonacoEditorWidgetSchema } from './schema';
+
+@Component({
+ selector: 'sf-widget-monaco-editor',
+ template: `
+
+
+
+ `
+})
+export class MonacoEditorWidget extends ControlUIWidget {
+ static readonly KEY = 'monaco-editor';
+
+ _change(value: string): void {
+ this.setValue(value);
+ if (this.ui.change) this.ui.change(value);
+ }
+
+ _event(ev: NuMonacoEditorEvent): void {
+ if (this.ui.event) this.ui.event(ev);
+ }
+}
diff --git a/packages/form/widgets-third/tinymce/demo/simple.md b/packages/form/widgets-third/tinymce/demo/simple.md
index aa3747179c..56759c9d25 100644
--- a/packages/form/widgets-third/tinymce/demo/simple.md
+++ b/packages/form/widgets-third/tinymce/demo/simple.md
@@ -15,12 +15,14 @@ Simplest of usage.
```ts
import { Component } from '@angular/core';
+
import { SFSchema } from '@delon/form';
+import type { TinymceWidgetSchema } from '@delon/form/widgets-third/tinymce';
import { NzMessageService } from 'ng-zorro-antd/message';
@Component({
selector: 'app-demo',
- template: ``,
+ template: ``
})
export class DemoComponent {
schema: SFSchema = {
@@ -29,10 +31,10 @@ export class DemoComponent {
type: 'string',
title: '描述',
ui: {
- widget: 'tinymce',
- },
- },
- },
+ widget: 'tinymce'
+ } as TinymceWidgetSchema
+ }
+ }
};
constructor(private msg: NzMessageService) {}
diff --git a/packages/form/widgets-third/tinymce/index.en-US.md b/packages/form/widgets-third/tinymce/index.en-US.md
index 971f772c2d..59da25000f 100644
--- a/packages/form/widgets-third/tinymce/index.en-US.md
+++ b/packages/form/widgets-third/tinymce/index.en-US.md
@@ -4,9 +4,9 @@ subtitle: Tinymce Rich Text
type: Third Widgets
---
-Tinymce rich text
+Tinymce rich text.
-> Note: third party widget is not registered by default, see details from [Customize Widgets](https://ng-alain.com/form/customize/en).
+## How to Use
**Installation dependencies**
@@ -14,68 +14,12 @@ Since the Tinymce editor relies on a third-party plug-in [ngx-tinymce](https://g
`npm i -S ngx-tinymce`
-
**Import module**
-- The project built using the latest scaffolding provides a third-party widget registration entry: `src/app/shared/json-schema/json-schema.module.ts`.
-- `TinymceWidget` needs to be declared in `JsonSchemaModule`.
-- Take the given plug-in list and toolbar as a full list, which can be deleted according to needs.
-
-```ts
-export const SCHEMA_THIRDS_COMPONENTS = [TinymceWidget];
-
-@NgModule({
- declarations: SCHEMA_THIRDS_COMPONENTS,
- imports: [
- SharedModule,
- DelonFormModule.forRoot(),
- NgxTinymceModule.forRoot({
- baseURL: './assets/tinymce/',
- config: {
- language: 'zh_CN',
- language_url: './assets/tinymce/langs/zh_CN.js',
- branding: false,
- paste_data_images: true,
- automatic_uploads: false,
- menubar: true,
- toolbar_mode: 'wrap',
- plugins:
- 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount image textpattern help emoticons autosave autoresize',
- toolbar:
- 'code undo redo restoredraft | cut copy | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | indent2em'
- }
- })
- ],
- exports: SCHEMA_THIRDS_COMPONENTS
-})
-export class JsonSchemaModule {
-}
-```
-
-**Widget registration**
-
-- Register the widget to the `WidgetRegistry` registry
-
-```ts
-export class JsonSchemaModule {
- constructor(widgetRegistry: WidgetRegistry) {
- widgetRegistry.register(TinymceWidget.KEY, TinymceWidget);
- }
-}
-```
-
-**Import resources**
-
-Tinymce supports a highly customized plug-in mode, which can effectively reduce the size of the package body by configuring plug-ins and static resources.
-
-- Plug-in download: [CustomBuilds](https://www.tiny.cloud/get-tiny/custom-builds/)
-- Language package download: [LanguagePackages](https://www.tiny.cloud/get-tiny/language-packages/)
-- Put the downloaded plug-in into a directory accessible by `baseURL`
-- Put the downloaded language pack into a directory accessible by `language_url`
-
-## Source Code
+- 1. Import `NgxTinymceModule.forRoot()` in `app.module.ts`
+- 2. Import `TinymceWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
-[Source Code](https://github.com/ng-alain/delon/tree/master/packages/form/widgets-third/tinymce)。
+> For more tinymce configuration, please refer to [ngx-tinymce](https://github.com/cipchk/ngx-tinymce).
## API
@@ -83,6 +27,10 @@ Tinymce supports a highly customized plug-in mode, which can effectively reduce
| Property | Description | Type | Default |
|----------|-------------|------|---------|
-| `[config]` | Configuration options, [official website](https://www.tinymce.com/docs/configure/integration-and-setup/) | `object` | - |
-| `[loading]` | Initial hint message | `string` | `加载中...` |
-| `[change]` | Callback function when content in editor is changed | `(html: string) => void` | - |
+| config | `any` | | see [configure](https://www.tinymce.com/docs/configure/integration-and-setup/) |
+| loading | `string,TemplateRef` | - | Loading status of tinymce |
+| disabled | `boolean` | `false` | Set tinymce mode is `readonly` if `true` |
+| inline | `boolean` | `false` | Inline editor |
+| delay | `number` | 0 | Delayed rendering, unit is 'millisecond' |
+| placeholder | `string` | - | Placeholder for tinymce, **NOTE:** dependent on [tinymce-placeholder](https://github.com/mohan/tinymce-placeholder) |
+| ready | `EventEmitter` | - | Tinymce ready callback |
diff --git a/packages/form/widgets-third/tinymce/index.ts b/packages/form/widgets-third/tinymce/index.ts
new file mode 100644
index 0000000000..79d7c1459f
--- /dev/null
+++ b/packages/form/widgets-third/tinymce/index.ts
@@ -0,0 +1,21 @@
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { NgxTinymceModule } from 'ngx-tinymce';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+
+import { TinymceWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, DelonFormModule, NgxTinymceModule],
+ declarations: [TinymceWidget]
+})
+export class TinymceWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(TinymceWidget.KEY, TinymceWidget);
+ }
+}
diff --git a/packages/form/widgets-third/tinymce/index.zh-CN.md b/packages/form/widgets-third/tinymce/index.zh-CN.md
index 8eff664e2f..9891838e53 100644
--- a/packages/form/widgets-third/tinymce/index.zh-CN.md
+++ b/packages/form/widgets-third/tinymce/index.zh-CN.md
@@ -6,79 +6,18 @@ type: Third Widgets
Tinymce富文本。
-> 注:第三方小部件默认并未注册,细节见[定制小部件](https://ng-alain.com/form/customize)。
-
-
## 如何使用
-**安装依赖**
-
-由于Tinymce编辑器依赖第三方插件[ngx-tinymce](https://github.com/cipchk/ngx-tinymce),所以使用时应首先安装依赖
+**安装依赖**
`npm i -S ngx-tinymce`
**导入模块**
-- 使用最新脚手架搭建出的项目提供了第三方控件注册入口: `src/app/shared/json-schema/json-schema.module.ts`
-- 需将`TinymceWidget`在`JsonSchemaModule`中进行声明
-- 以给出的插件列表与工具栏为全量列表,可根据需求删减
-
-```ts
-export const SCHEMA_THIRDS_COMPONENTS = [TinymceWidget];
-
-@NgModule({
- declarations: SCHEMA_THIRDS_COMPONENTS,
- imports: [
- SharedModule,
- DelonFormModule.forRoot(),
- NgxTinymceModule.forRoot({
- baseURL: './assets/tinymce/',
- config: {
- language: 'zh_CN',
- language_url: './assets/tinymce/langs/zh_CN.js',
- branding: false,
- paste_data_images: true,
- automatic_uploads: false,
- menubar: true,
- toolbar_mode: 'wrap',
- plugins:
- 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount image textpattern help emoticons autosave autoresize',
- toolbar:
- 'code undo redo restoredraft | cut copy | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | indent2em'
- }
- })
- ],
- exports: SCHEMA_THIRDS_COMPONENTS
-})
-export class JsonSchemaModule {
-}
-```
-
-**控件注册**
-
-- 将控件注册到`WidgetRegistry`注册表中
-
-```ts
-export class JsonSchemaModule {
- constructor(widgetRegistry: WidgetRegistry) {
- widgetRegistry.register(TinymceWidget.KEY, TinymceWidget);
- }
-}
-```
-
-**导入静态资源**
-
-Tinymce支持高度自定义的插件模式,通过配置插件和静态资源可以有效的减少包体体积
-
-- 插件下载: [CustomBuilds](https://www.tiny.cloud/get-tiny/custom-builds/)
-- 语言包下载: [LanguagePackages](https://www.tiny.cloud/get-tiny/language-packages/)
-- 将下载好的插件放入`baseURL`可访问到的目录内
-- 将下载好的语言包放入`language_url`可访问到的目录内
-
-
-## 源代码
+- 1、在 `app.module.ts` 下导入 `NgxTinymceModule.forRoot()`
+- 2、在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `TinymceWidgetModule`。
-[源代码](https://github.com/ng-alain/delon/tree/master/packages/form/widgets-third/tinymce)。
+> 关于更多 tinymce 配置请参考 [ngx-tinymce](https://github.com/cipchk/ngx-tinymce)。
## API
@@ -86,6 +25,10 @@ Tinymce支持高度自定义的插件模式,通过配置插件和静态资源可
| 成员 | 说明 | 类型 | 默认值 |
|----|----|----|-----|
-| `[config]` | 配置项说明,[见官网](https://www.tinymce.com/docs/configure/integration-and-setup/) | `object` | - |
-| `[loading]` | 初始化提示文本 | `string` | `加载中...` |
-| `[change]` | 编辑器内容发生改变时会触发该事件 | `(html: string) => void` | - |
+| config | `any` | | see [configure](https://www.tinymce.com/docs/configure/integration-and-setup/) |
+| loading | `string,TemplateRef` | - | Loading status of tinymce |
+| disabled | `boolean` | `false` | Set tinymce mode is `readonly` if `true` |
+| inline | `boolean` | `false` | Inline editor |
+| delay | `number` | 0 | Delayed rendering, unit is 'millisecond' |
+| placeholder | `string` | - | Placeholder for tinymce, **NOTE:** dependent on [tinymce-placeholder](https://github.com/mohan/tinymce-placeholder) |
+| ready | `EventEmitter` | - | Tinymce ready callback |
diff --git a/packages/form/widgets-third/tinymce/ng-package.json b/packages/form/widgets-third/tinymce/ng-package.json
new file mode 100644
index 0000000000..ff7c84a23d
--- /dev/null
+++ b/packages/form/widgets-third/tinymce/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-third-tinymce",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/widgets-third/tinymce/schema.ts b/packages/form/widgets-third/tinymce/schema.ts
new file mode 100644
index 0000000000..19a34fc9f6
--- /dev/null
+++ b/packages/form/widgets-third/tinymce/schema.ts
@@ -0,0 +1,12 @@
+import type { SFUISchemaItem } from '@delon/form';
+import type { NzSafeAny } from 'ng-zorro-antd/core/types';
+
+export interface TinymceWidgetSchema extends SFUISchemaItem {
+ /** 默认配置项,对全局 Tinymce 有效 */
+ config?: Record;
+ inline?: boolean;
+ /** 延迟加载(单位:毫秒),默认:`0` */
+ delay?: number;
+ loading?: string;
+ ready?: (instance: NzSafeAny) => void;
+}
diff --git a/packages/form/widgets-third/tinymce/tinymce.widget.ts b/packages/form/widgets-third/tinymce/tinymce.widget.ts
deleted file mode 100644
index 6594d5b652..0000000000
--- a/packages/form/widgets-third/tinymce/tinymce.widget.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-
-import { ControlWidget } from '@delon/form';
-
-@Component({
- selector: 'sf-tinymce',
- template: `
-
-
-
- `
-})
-export class TinymceWidget extends ControlWidget implements OnInit {
- static readonly KEY = 'tinymce';
-
- config!: Record;
- loading!: string;
-
- ngOnInit(): void {
- this.loading = this.ui.loading || '加载中……';
- this.config = this.ui.config || {};
- }
-
- change(value: string): void {
- if (this.ui.change) this.ui.change(value);
- this.setValue(value);
- }
-}
diff --git a/packages/form/widgets-third/tinymce/widget.ts b/packages/form/widgets-third/tinymce/widget.ts
new file mode 100644
index 0000000000..412831a07d
--- /dev/null
+++ b/packages/form/widgets-third/tinymce/widget.ts
@@ -0,0 +1,42 @@
+import { Component } from '@angular/core';
+
+import { ControlUIWidget } from '@delon/form';
+import type { NzSafeAny } from 'ng-zorro-antd/core/types';
+
+import type { TinymceWidgetSchema } from './schema';
+
+@Component({
+ selector: 'sf-widget-tinymce',
+ template: `
+
+
+
+ `
+})
+export class TinymceWidget extends ControlUIWidget {
+ static readonly KEY = 'tinymce';
+
+ change(value: string): void {
+ this.setValue(value);
+ if (this.ui.change) this.ui.change(value);
+ }
+
+ _ready(instance: NzSafeAny): void {
+ if (this.ui.ready) this.ui.ready(instance);
+ }
+}
diff --git a/packages/form/src/widgets/autocomplete/demo/simple.md b/packages/form/widgets/autocomplete/demo/simple.md
similarity index 91%
rename from packages/form/src/widgets/autocomplete/demo/simple.md
rename to packages/form/widgets/autocomplete/demo/simple.md
index 93a117f613..b55386039e 100644
--- a/packages/form/src/widgets/autocomplete/demo/simple.md
+++ b/packages/form/widgets/autocomplete/demo/simple.md
@@ -15,7 +15,8 @@ Simplest of usage.
```ts
import { Component } from '@angular/core';
-import { SFAutoCompleteWidgetSchema, SFSchema } from '@delon/form';
+import { SFSchema } from '@delon/form';
+import type { SFAutoCompleteWidgetSchema } from '@delon/form/widgets/autocomplete';
import { NzMessageService } from 'ng-zorro-antd/message';
import { of } from 'rxjs';
diff --git a/packages/form/src/widgets/autocomplete/index.en-US.md b/packages/form/widgets/autocomplete/index.en-US.md
similarity index 90%
rename from packages/form/src/widgets/autocomplete/index.en-US.md
rename to packages/form/widgets/autocomplete/index.en-US.md
index b2d5042f8c..8425bf704c 100644
--- a/packages/form/src/widgets/autocomplete/index.en-US.md
+++ b/packages/form/widgets/autocomplete/index.en-US.md
@@ -1,11 +1,15 @@
---
title: autocomplete
subtitle: Autocomplete
-type: Widgets
+type: Non-built-in widgets
---
Input complete automatically.
+## Import module
+
+Non-built-in modules, Should be import `AutoCompleteWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
+
## Data Source
**Static**
diff --git a/packages/form/widgets/autocomplete/index.ts b/packages/form/widgets/autocomplete/index.ts
new file mode 100644
index 0000000000..6229fa2be8
--- /dev/null
+++ b/packages/form/widgets/autocomplete/index.ts
@@ -0,0 +1,22 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+import { NzAutocompleteModule } from 'ng-zorro-antd/auto-complete';
+import { NzInputModule } from 'ng-zorro-antd/input';
+
+import { AutoCompleteWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, DelonFormModule, CommonModule, NzInputModule, NzAutocompleteModule],
+ declarations: [AutoCompleteWidget]
+})
+export class AutoCompleteWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(AutoCompleteWidget.KEY, AutoCompleteWidget);
+ }
+}
diff --git a/packages/form/src/widgets/autocomplete/index.zh-CN.md b/packages/form/widgets/autocomplete/index.zh-CN.md
similarity index 90%
rename from packages/form/src/widgets/autocomplete/index.zh-CN.md
rename to packages/form/widgets/autocomplete/index.zh-CN.md
index 2baeea393b..859f4e6860 100644
--- a/packages/form/src/widgets/autocomplete/index.zh-CN.md
+++ b/packages/form/widgets/autocomplete/index.zh-CN.md
@@ -1,11 +1,15 @@
---
title: autocomplete
subtitle: 自动完成
-type: Widgets
+type: Non-built-in widgets
---
输入框自动完成功能。
+## 导入模块
+
+非内置模块,需要额外在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `AutoCompleteWidgetModule`。
+
## 数据源说明
**静态**
diff --git a/packages/form/widgets/autocomplete/ng-package.json b/packages/form/widgets/autocomplete/ng-package.json
new file mode 100644
index 0000000000..9d4a9afb0e
--- /dev/null
+++ b/packages/form/widgets/autocomplete/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-auto-complete",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/src/widgets/autocomplete/schema.ts b/packages/form/widgets/autocomplete/schema.ts
similarity index 89%
rename from packages/form/src/widgets/autocomplete/schema.ts
rename to packages/form/widgets/autocomplete/schema.ts
index dfa5243218..abe50891f7 100644
--- a/packages/form/src/widgets/autocomplete/schema.ts
+++ b/packages/form/widgets/autocomplete/schema.ts
@@ -1,11 +1,9 @@
import { Observable } from 'rxjs';
-import { NzAutocompleteOptionComponent } from 'ng-zorro-antd/auto-complete';
+import type { SFSchemaEnum, SFSchemaEnumType, SFUISchemaItem } from '@delon/form';
+import type { NzAutocompleteOptionComponent } from 'ng-zorro-antd/auto-complete';
import type { CompareWith } from 'ng-zorro-antd/core/types';
-import type { SFSchemaEnum, SFSchemaEnumType } from '../../schema';
-import type { SFUISchemaItem } from '../../schema/ui';
-
export interface SFAutoCompleteWidgetSchema extends SFUISchemaItem {
/**
* 异步静态数据源
diff --git a/packages/form/src/widgets/autocomplete/autocomplete.widget.spec.ts b/packages/form/widgets/autocomplete/widget.spec.ts
similarity index 96%
rename from packages/form/src/widgets/autocomplete/autocomplete.widget.spec.ts
rename to packages/form/widgets/autocomplete/widget.spec.ts
index dc67d71d23..3a7e75c333 100644
--- a/packages/form/src/widgets/autocomplete/autocomplete.widget.spec.ts
+++ b/packages/form/widgets/autocomplete/widget.spec.ts
@@ -2,15 +2,15 @@ import { DebugElement } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
import { of } from 'rxjs';
+import { mergeConfig, SFSchema, SFSchemaEnum } from '@delon/form';
import { createTestContext } from '@delon/testing';
import { AlainConfigService } from '@delon/util/config';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
-import { AutoCompleteWidget } from './autocomplete.widget';
+import { AutoCompleteWidgetModule } from './index';
import { SFAutoCompleteWidgetSchema } from './schema';
-import { configureSFTestSuite, SFPage, TestFormComponent } from '../../../spec/base.spec';
-import { SFSchema, SFSchemaEnum } from '../../../src/schema/index';
-import { mergeConfig } from '../../config';
+import { AutoCompleteWidget } from './widget';
+import { configureSFTestSuite, SFPage, TestFormComponent } from '../../spec/base.spec';
describe('form: widget: autocomplete', () => {
let fixture: ComponentFixture;
@@ -19,7 +19,7 @@ describe('form: widget: autocomplete', () => {
let page: SFPage;
const widget = 'autocomplete';
- configureSFTestSuite();
+ configureSFTestSuite({ imports: [AutoCompleteWidgetModule] });
beforeEach(() => {
({ fixture, dl, context } = createTestContext(TestFormComponent));
diff --git a/packages/form/src/widgets/autocomplete/autocomplete.widget.ts b/packages/form/widgets/autocomplete/widget.ts
similarity index 74%
rename from packages/form/src/widgets/autocomplete/autocomplete.widget.ts
rename to packages/form/widgets/autocomplete/widget.ts
index 2a0acb9fd2..68c87215ec 100644
--- a/packages/form/src/widgets/autocomplete/autocomplete.widget.ts
+++ b/packages/form/widgets/autocomplete/widget.ts
@@ -2,22 +2,54 @@ import { Component, ViewChild, ViewEncapsulation } from '@angular/core';
import { NgModel } from '@angular/forms';
import { Observable, of, debounceTime, map, mergeMap, startWith, takeUntil } from 'rxjs';
+import { ControlUIWidget, SFSchemaEnum, SFValue, getCopyEnum, getEnum, toBool } from '@delon/form';
import { NzAutocompleteOptionComponent } from 'ng-zorro-antd/auto-complete';
import type { NzSafeAny } from 'ng-zorro-antd/core/types';
-import { SFAutoCompleteWidgetSchema } from './schema';
-import { SFValue } from '../../interface';
-import { SFSchemaEnum } from '../../schema';
-import { getCopyEnum, getEnum, toBool } from '../../utils';
-import { ControlUIWidget } from '../../widget';
+import type { SFAutoCompleteWidgetSchema } from './schema';
@Component({
selector: 'sf-autocomplete',
- templateUrl: './autocomplete.widget.html',
+ template: `
+
+
+ {{ i.label }}
+
+ `,
preserveWhitespaces: false,
encapsulation: ViewEncapsulation.None
})
export class AutoCompleteWidget extends ControlUIWidget {
+ static readonly KEY = 'autocomplete';
+
i: NzSafeAny = {};
list!: Observable;
typing: string = '';
diff --git a/packages/form/src/widgets/cascader/demo/simple.md b/packages/form/widgets/cascader/demo/simple.md
similarity index 95%
rename from packages/form/src/widgets/cascader/demo/simple.md
rename to packages/form/widgets/cascader/demo/simple.md
index cf042d1e60..d12e5397fb 100644
--- a/packages/form/src/widgets/cascader/demo/simple.md
+++ b/packages/form/widgets/cascader/demo/simple.md
@@ -15,7 +15,8 @@ Simplest of usage.
```ts
import { Component } from '@angular/core';
-import { SFCascaderWidgetSchema, SFSchema } from '@delon/form';
+import { SFSchema } from '@delon/form';
+import type { SFCascaderWidgetSchema } from '@delon/form/widgets/cascader';
import { NzMessageService } from 'ng-zorro-antd/message';
@Component({
diff --git a/packages/form/src/widgets/cascader/index.en-US.md b/packages/form/widgets/cascader/index.en-US.md
similarity index 92%
rename from packages/form/src/widgets/cascader/index.en-US.md
rename to packages/form/widgets/cascader/index.en-US.md
index 2133f875a4..858fa11a6b 100644
--- a/packages/form/src/widgets/cascader/index.en-US.md
+++ b/packages/form/widgets/cascader/index.en-US.md
@@ -1,11 +1,15 @@
---
title: cascader
subtitle: Cascader
-type: Widgets
+type: Non-built-in widgets
---
Usually, it's used in province/city/district, company hierarchy, category of things, etc.
+## Import module
+
+Non-built-in modules, Should be import `CascaderWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
+
## Note
- Value of `default` or `formData` should always be an array, for example, city cascade may only save leaf node `value`, but you need to manually provide the whole data chain `value` array
diff --git a/packages/form/widgets/cascader/index.ts b/packages/form/widgets/cascader/index.ts
new file mode 100644
index 0000000000..dfd30c8898
--- /dev/null
+++ b/packages/form/widgets/cascader/index.ts
@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+import { NzCascaderModule } from 'ng-zorro-antd/cascader';
+
+import { CascaderWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, DelonFormModule, NzCascaderModule],
+ declarations: [CascaderWidget]
+})
+export class CascaderWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(CascaderWidget.KEY, CascaderWidget);
+ }
+}
diff --git a/packages/form/src/widgets/cascader/index.zh-CN.md b/packages/form/widgets/cascader/index.zh-CN.md
similarity index 92%
rename from packages/form/src/widgets/cascader/index.zh-CN.md
rename to packages/form/widgets/cascader/index.zh-CN.md
index 9faa425356..2d7280c692 100644
--- a/packages/form/src/widgets/cascader/index.zh-CN.md
+++ b/packages/form/widgets/cascader/index.zh-CN.md
@@ -1,11 +1,15 @@
---
title: cascader
subtitle: 级联选择
-type: Widgets
+type: Non-built-in widgets
---
一般用于省市区,公司层级,事物分类等。
+## 导入模块
+
+非内置模块,需要额外在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `CascaderWidgetModule`。
+
## 注意事项
- `default` 或 `formData` 值始终应该保持一个数组,例如:城市级联可能只存储叶节点 `value`,此时需要手动处理并给出完整数据链 `value` 数组
diff --git a/packages/form/widgets/cascader/ng-package.json b/packages/form/widgets/cascader/ng-package.json
new file mode 100644
index 0000000000..69f4052d28
--- /dev/null
+++ b/packages/form/widgets/cascader/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-cascader",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/src/widgets/cascader/schema.ts b/packages/form/widgets/cascader/schema.ts
similarity index 96%
rename from packages/form/src/widgets/cascader/schema.ts
rename to packages/form/widgets/cascader/schema.ts
index 09f7068c45..b3bcc9d09b 100644
--- a/packages/form/src/widgets/cascader/schema.ts
+++ b/packages/form/widgets/cascader/schema.ts
@@ -1,8 +1,8 @@
+import { SFUISchemaItem } from '@delon/form';
import { NzCascaderExpandTrigger, NzCascaderOption, NzShowSearchOptions } from 'ng-zorro-antd/cascader';
import { NgStyleInterface, NzSafeAny } from 'ng-zorro-antd/core/types';
-import { CascaderWidget } from './cascader.widget';
-import { SFUISchemaItem } from '../../schema/ui';
+import type { CascaderWidget } from './widget';
export interface SFCascaderWidgetSchema extends SFUISchemaItem {
/**
diff --git a/packages/form/src/widgets/cascader/cascader.widget.spec.ts b/packages/form/widgets/cascader/widget.spec.ts
similarity index 95%
rename from packages/form/src/widgets/cascader/cascader.widget.spec.ts
rename to packages/form/widgets/cascader/widget.spec.ts
index f0c60873a3..509c5af744 100644
--- a/packages/form/src/widgets/cascader/cascader.widget.spec.ts
+++ b/packages/form/widgets/cascader/widget.spec.ts
@@ -3,8 +3,9 @@ import { ComponentFixture, fakeAsync } from '@angular/core/testing';
import { createTestContext } from '@delon/testing';
-import { CascaderWidget } from './cascader.widget';
-import { configureSFTestSuite, SFPage, TestFormComponent } from '../../../spec/base.spec';
+import { CascaderWidgetModule } from './index';
+import { CascaderWidget } from './widget';
+import { configureSFTestSuite, SFPage, TestFormComponent } from '../../spec/base.spec';
describe('form: widget: cascader', () => {
let fixture: ComponentFixture;
@@ -13,7 +14,7 @@ describe('form: widget: cascader', () => {
let page: SFPage;
const widget = 'cascader';
- configureSFTestSuite();
+ configureSFTestSuite({ imports: [CascaderWidgetModule] });
beforeEach(() => {
({ fixture, dl, context } = createTestContext(TestFormComponent));
diff --git a/packages/form/src/widgets/cascader/cascader.widget.ts b/packages/form/widgets/cascader/widget.ts
similarity index 56%
rename from packages/form/src/widgets/cascader/cascader.widget.ts
rename to packages/form/widgets/cascader/widget.ts
index 63ff4b8101..3c78f69318 100644
--- a/packages/form/src/widgets/cascader/cascader.widget.ts
+++ b/packages/form/widgets/cascader/widget.ts
@@ -1,21 +1,54 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
+import { ControlUIWidget, SFSchemaEnum, SFValue, getData, toBool } from '@delon/form';
import { NzCascaderOption } from 'ng-zorro-antd/cascader';
import type { NzSafeAny } from 'ng-zorro-antd/core/types';
-import { SFCascaderWidgetSchema } from './schema';
-import { SFValue } from '../../interface';
-import { SFSchemaEnum } from '../../schema';
-import { getData, toBool } from '../../utils';
-import { ControlUIWidget } from '../../widget';
+import type { SFCascaderWidgetSchema } from './schema';
@Component({
selector: 'sf-cascader',
- templateUrl: './cascader.widget.html',
+ template: `
+
+ `,
preserveWhitespaces: false,
encapsulation: ViewEncapsulation.None
})
export class CascaderWidget extends ControlUIWidget implements OnInit {
+ static readonly KEY = 'cascader';
+
clearText!: string;
showArrow!: boolean;
showInput!: boolean;
diff --git a/packages/form/widgets/color/demo/simple.md b/packages/form/widgets/color/demo/simple.md
new file mode 100644
index 0000000000..5cd26ed1ba
--- /dev/null
+++ b/packages/form/widgets/color/demo/simple.md
@@ -0,0 +1,106 @@
+---
+title:
+ zh-CN: 基础样例
+ en-US: Basic Usage
+order: 0
+---
+
+## zh-CN
+
+最简单的用法。
+
+## en-US
+
+Simplest of usage.
+
+```ts
+import { Component } from '@angular/core';
+
+import { SFSchema } from '@delon/form';
+import type { SFColorWidgetSchema } from '@delon/form/widgets/color';
+import { NzMessageService } from 'ng-zorro-antd/message';
+
+@Component({
+ selector: 'app-demo',
+ template: ``
+})
+export class DemoComponent {
+ schema: SFSchema = {
+ properties: {
+ base: {
+ type: 'string',
+ title: 'Base',
+ ui: {
+ widget: 'color',
+ title: 'Pls choose a color',
+ change: console.log
+ } as SFColorWidgetSchema
+ },
+ showText: {
+ type: 'string',
+ title: 'Show Text',
+ ui: {
+ widget: 'color',
+ showText: true,
+ trigger: 'hover',
+ change: console.log
+ } as SFColorWidgetSchema
+ },
+ defaultValue: {
+ type: 'string',
+ title: 'Default Value',
+ ui: {
+ widget: 'color',
+ showText: true,
+ defaultValue: '#0a0',
+ change: console.log
+ } as SFColorWidgetSchema
+ },
+ clearColor: {
+ type: 'string',
+ title: 'Clear Color',
+ ui: {
+ widget: 'color',
+ allowClear: true,
+ change: console.log
+ } as SFColorWidgetSchema
+ },
+ disabled: {
+ type: 'string',
+ title: 'Disabled',
+ ui: {
+ widget: 'color',
+ showText: true
+ } as SFColorWidgetSchema,
+ readOnly: true
+ },
+ rgb: {
+ type: 'string',
+ title: 'RGB',
+ ui: {
+ widget: 'color',
+ format: 'rgb',
+ showText: true,
+ change: console.log,
+ formatChange: console.log
+ } as SFColorWidgetSchema
+ },
+ block: {
+ type: 'string',
+ title: 'Block Color',
+ ui: {
+ widget: 'color',
+ block: true
+ } as SFColorWidgetSchema,
+ default: '#f50'
+ }
+ }
+ };
+
+ constructor(private msg: NzMessageService) {}
+
+ submit(value: {}): void {
+ this.msg.success(JSON.stringify(value));
+ }
+}
+```
diff --git a/packages/form/widgets/color/index.en-US.md b/packages/form/widgets/color/index.en-US.md
new file mode 100644
index 0000000000..5bf803ec77
--- /dev/null
+++ b/packages/form/widgets/color/index.en-US.md
@@ -0,0 +1,33 @@
+---
+title: color
+subtitle: Color
+type: Non-built-in widgets
+---
+
+Used when the user needs to customize the color selection.
+
+## How to Use
+
+**Installation dependencies**
+
+`yarn add ng-antd-color-picker`
+
+**Import Module**
+
+Non-built-in modules, Should be import `ColorWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
+
+## API
+
+### ui
+
+| Property | Description | Type | Default |
+|----------|-------------|------|---------|
+| `[format]` | Format of color | `rgb`|`hex`|`hsb` | `hex` |
+| `[defaultValue]` | Default value of color | `string`|`NzColor` | `false` |
+| `[allowClear]` | Allow clearing color selected | `boolean` | `false` |
+| `[trigger]` | ColorPicker trigger mode | `hover`|`click` | `click` |
+| `[showText]` | Show color text | `boolean` | `false` |
+| `[title]` | Setting the title of the color picker | `TemplateRef`|`string` | - |
+| `(change)` | Callback when value is changed | `EventEmitter<{ color: NzColor; format: string }>` | - |
+| `(formatChange)` | Callback when `format` is changed | `EventEmitter<'rgb'|'hex'|'hsb'>` | - |
+| `[block]` | Color Block | `boolean` | `false` |
diff --git a/packages/form/widgets/color/index.ts b/packages/form/widgets/color/index.ts
new file mode 100644
index 0000000000..277a3f31cd
--- /dev/null
+++ b/packages/form/widgets/color/index.ts
@@ -0,0 +1,21 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+import { NzColorPickerModule } from 'ng-zorro-antd/color-picker';
+
+import { ColorWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, CommonModule, DelonFormModule, NzColorPickerModule],
+ declarations: [ColorWidget]
+})
+export class ColorWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(ColorWidget.KEY, ColorWidget);
+ }
+}
diff --git a/packages/form/widgets/color/index.zh-CN.md b/packages/form/widgets/color/index.zh-CN.md
new file mode 100644
index 0000000000..da9644edda
--- /dev/null
+++ b/packages/form/widgets/color/index.zh-CN.md
@@ -0,0 +1,33 @@
+---
+title: color
+subtitle: 颜色
+type: Non-built-in widgets
+---
+
+当用户需要自定义颜色选择的时候使用。
+
+## 如何使用
+
+**安装依赖**
+
+`yarn add ng-antd-color-picker`
+
+**导入模块**
+
+非内置模块,需要额外在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `ColorWidgetModule`。
+
+## API
+
+### ui 属性
+
+| 成员 | 说明 | 类型 | 默认值 |
+|----|----|----|-----|
+| `[format]` | 颜色格式 | `rgb`|`hex`|`hsb` | `hex` |
+| `[defaultValue]` | 颜色默认的值 | `string`|`NzColor` | - |
+| `[allowClear]` | 允许清除选择的颜色 | `boolean` | `false` |
+| `[trigger]` | 颜色选择器的触发模式 | `hover`|`click` | `click` |
+| `[showText]` | 显示颜色文本 | `boolean` | `false` |
+| `[title]` | 设置颜色选择器的标题 | `TemplateRef`|`string` | - |
+| `(change)` | 颜色变化的回调 | `EventEmitter<{ color: NzColor; format: string }>` | - |
+| `(formatChange)` | 颜色格式变化的回调 | `EventEmitter<'rgb'|'hex'|'hsb'>` | - |
+| `[block]` | 是否颜色块 | `boolean` | `false` |
diff --git a/packages/form/widgets/color/ng-package.json b/packages/form/widgets/color/ng-package.json
new file mode 100644
index 0000000000..ec57a9fa30
--- /dev/null
+++ b/packages/form/widgets/color/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-color",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/widgets/color/schema.ts b/packages/form/widgets/color/schema.ts
new file mode 100644
index 0000000000..819eefe595
--- /dev/null
+++ b/packages/form/widgets/color/schema.ts
@@ -0,0 +1,47 @@
+import type { TemplateRef } from '@angular/core';
+
+import type { SFUISchemaItem } from '@delon/form';
+import type { NzColor, NzColorPickerFormatType, NzColorPickerTriggerType } from 'ng-zorro-antd/color-picker';
+
+export interface SFColorWidgetSchema extends SFUISchemaItem {
+ /**
+ * Format of color
+ */
+ format?: NzColorPickerFormatType | null;
+ /**
+ * Default value of color
+ */
+ defaultValue?: string | NzColor | null;
+ /**
+ * ColorPicker trigger mode
+ */
+ trigger?: NzColorPickerTriggerType | null;
+ /**
+ * Setting the title of the color picker
+ */
+ title?: TemplateRef | string;
+ /**
+ * Triggers for customizing color panels.
+ */
+ flipFlop?: TemplateRef | string | null;
+ /**
+ * Show color text
+ */
+ showText?: boolean;
+ /**
+ * Allow clearing color selected
+ */
+ allowClear?: boolean;
+ /**
+ * Callback when value is changed
+ */
+ change?: (ev: { color: NzColor; format: string }) => void;
+ /**
+ * Callback when `format` is changed
+ */
+ formatChange?: (color: NzColorPickerFormatType) => void;
+ /**
+ * Color Block
+ */
+ block?: boolean;
+}
diff --git a/packages/form/widgets/color/widget.spec.ts b/packages/form/widgets/color/widget.spec.ts
new file mode 100644
index 0000000000..b5f9825fee
--- /dev/null
+++ b/packages/form/widgets/color/widget.spec.ts
@@ -0,0 +1,49 @@
+import { DebugElement } from '@angular/core';
+import { ComponentFixture, fakeAsync } from '@angular/core/testing';
+
+import { SFSchema } from '@delon/form';
+import { createTestContext } from '@delon/testing';
+
+import { ColorWidgetModule, SFColorWidgetSchema } from './index';
+import { configureSFTestSuite, SFPage, TestFormComponent } from '../../spec/base.spec';
+
+describe('form: widget: color', () => {
+ let fixture: ComponentFixture;
+ let dl: DebugElement;
+ let context: TestFormComponent;
+ let page: SFPage;
+
+ configureSFTestSuite({ imports: [ColorWidgetModule] });
+
+ beforeEach(() => {
+ ({ fixture, dl, context } = createTestContext(TestFormComponent));
+ page = new SFPage(context.comp);
+ page.cleanOverlay().prop(dl, context, fixture);
+ });
+
+ it('should be working', fakeAsync(() => {
+ const change = jasmine.createSpy();
+ const formatChange = jasmine.createSpy();
+ const s: SFSchema = {
+ properties: {
+ a: {
+ type: 'string',
+ ui: {
+ widget: 'color',
+ defaultValue: '#f50',
+ change,
+ formatChange
+ } as SFColorWidgetSchema
+ }
+ }
+ };
+ page
+ .newSchema(s)
+ .typeEvent('click', '.ant-color-picker-trigger')
+ .typeEvent('click', 'nz-select')
+ .typeEvent('click', 'nz-option-container nz-option-item:nth-child(2)');
+ expect(page.getValue('/a')).toBe('hsb(20, 100%, 100%)');
+ expect(change).toHaveBeenCalled();
+ expect(formatChange).toHaveBeenCalled();
+ }));
+});
diff --git a/packages/form/widgets/color/widget.ts b/packages/form/widgets/color/widget.ts
new file mode 100644
index 0000000000..eebad6c6a8
--- /dev/null
+++ b/packages/form/widgets/color/widget.ts
@@ -0,0 +1,49 @@
+import { Component, ViewEncapsulation } from '@angular/core';
+
+import { ControlUIWidget } from '@delon/form';
+import type { NzColor, NzColorPickerFormatType } from 'ng-zorro-antd/color-picker';
+
+import type { SFColorWidgetSchema } from './schema';
+
+@Component({
+ selector: 'sf-color',
+ template: `
+
+
+ `,
+ preserveWhitespaces: false,
+ encapsulation: ViewEncapsulation.None
+})
+export class ColorWidget extends ControlUIWidget {
+ static readonly KEY = 'color';
+
+ _change(ev: { color: NzColor; format: string }): void {
+ if (this.ui.change) this.ui.change(ev);
+ }
+
+ _formatChange(ev: NzColorPickerFormatType): void {
+ if (this.ui.formatChange) this.ui.formatChange(ev);
+ }
+}
diff --git a/packages/form/src/widgets/mention/demo/simple.md b/packages/form/widgets/mention/demo/simple.md
similarity index 93%
rename from packages/form/src/widgets/mention/demo/simple.md
rename to packages/form/widgets/mention/demo/simple.md
index 3f11d108a6..4b7446c3da 100644
--- a/packages/form/src/widgets/mention/demo/simple.md
+++ b/packages/form/widgets/mention/demo/simple.md
@@ -15,7 +15,8 @@ Simplest of usage.
```ts
import { Component } from '@angular/core';
-import { SFMentionWidgetSchema, SFSchema } from '@delon/form';
+import { SFSchema } from '@delon/form';
+import type { SFMentionWidgetSchema } from '@delon/form/widgets/mention';
import { MentionOnSearchTypes } from 'ng-zorro-antd/mention';
import { NzMessageService } from 'ng-zorro-antd/message';
import { of, delay } from 'rxjs';
diff --git a/packages/form/src/widgets/mention/index.en-US.md b/packages/form/widgets/mention/index.en-US.md
similarity index 87%
rename from packages/form/src/widgets/mention/index.en-US.md
rename to packages/form/widgets/mention/index.en-US.md
index 07032bb3b6..1629117690 100644
--- a/packages/form/src/widgets/mention/index.en-US.md
+++ b/packages/form/widgets/mention/index.en-US.md
@@ -1,11 +1,15 @@
---
title: mention
subtitle: Mention
-type: Widgets
+type: Non-built-in widgets
---
Mention widget.
+## Import module
+
+Non-built-in modules, Should be import `MentionWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
+
## Note
- You **must** set `valueWith` parameter if there is no `label` property in data.
diff --git a/packages/form/widgets/mention/index.ts b/packages/form/widgets/mention/index.ts
new file mode 100644
index 0000000000..d6d9db8080
--- /dev/null
+++ b/packages/form/widgets/mention/index.ts
@@ -0,0 +1,22 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+import { NzInputModule } from 'ng-zorro-antd/input';
+import { NzMentionModule } from 'ng-zorro-antd/mention';
+
+import { MentionWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, DelonFormModule, NzMentionModule, NzInputModule, CommonModule],
+ declarations: [MentionWidget]
+})
+export class MentionWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(MentionWidget.KEY, MentionWidget);
+ }
+}
diff --git a/packages/form/src/widgets/mention/index.zh-CN.md b/packages/form/widgets/mention/index.zh-CN.md
similarity index 87%
rename from packages/form/src/widgets/mention/index.zh-CN.md
rename to packages/form/widgets/mention/index.zh-CN.md
index 4fdc7e8f1b..53dac63338 100644
--- a/packages/form/src/widgets/mention/index.zh-CN.md
+++ b/packages/form/widgets/mention/index.zh-CN.md
@@ -1,11 +1,15 @@
---
title: mention
subtitle: 提及
-type: Widgets
+type: Non-built-in widgets
---
提及组件。
+## 导入模块
+
+非内置模块,需要额外在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `MentionWidgetModule`。
+
## 注意事项
- 若数据中不包括 `label` 属性,则**务必**指定 `valueWith` 参数。
diff --git a/packages/form/widgets/mention/ng-package.json b/packages/form/widgets/mention/ng-package.json
new file mode 100644
index 0000000000..ffc3837bae
--- /dev/null
+++ b/packages/form/widgets/mention/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-mention",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/src/widgets/mention/schema.ts b/packages/form/widgets/mention/schema.ts
similarity index 93%
rename from packages/form/src/widgets/mention/schema.ts
rename to packages/form/widgets/mention/schema.ts
index c05b4a813f..2af590e4fb 100644
--- a/packages/form/src/widgets/mention/schema.ts
+++ b/packages/form/widgets/mention/schema.ts
@@ -1,12 +1,10 @@
import { Observable } from 'rxjs';
+import type { SFSchemaEnumType, SFUISchemaItem } from '@delon/form';
import { NzSafeAny, NzSizeLDSType } from 'ng-zorro-antd/core/types';
import { AutoSizeType } from 'ng-zorro-antd/input';
import { MentionOnSearchTypes } from 'ng-zorro-antd/mention';
-import { SFSchemaEnumType } from '../../schema';
-import { SFUISchemaItem } from '../../schema/ui';
-
export interface SFMentionWidgetSchema extends SFUISchemaItem {
/**
* 异步静态数据源
diff --git a/packages/form/src/widgets/mention/mention.widget.spec.ts b/packages/form/widgets/mention/widget.spec.ts
similarity index 90%
rename from packages/form/src/widgets/mention/mention.widget.spec.ts
rename to packages/form/widgets/mention/widget.spec.ts
index ed1cf63304..bf32d585c2 100644
--- a/packages/form/src/widgets/mention/mention.widget.spec.ts
+++ b/packages/form/widgets/mention/widget.spec.ts
@@ -2,12 +2,13 @@ import { DebugElement } from '@angular/core';
import { ComponentFixture, fakeAsync } from '@angular/core/testing';
import { of } from 'rxjs';
+import type { SFSchema } from '@delon/form';
import { createTestContext } from '@delon/testing';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
-import { MentionWidget } from './mention.widget';
-import { configureSFTestSuite, SFPage, TestFormComponent } from '../../../spec/base.spec';
-import { SFSchema } from '../../../src/schema/index';
+import { MentionWidgetModule } from './index';
+import { MentionWidget } from './widget';
+import { configureSFTestSuite, SFPage, TestFormComponent } from '../../spec/base.spec';
const DATA = ['asdf', 'cipchk', '中文', 'にほんご'];
@@ -18,7 +19,7 @@ describe('form: widget: mention', () => {
let page: SFPage;
const widget = 'mention';
- configureSFTestSuite();
+ configureSFTestSuite({ imports: [MentionWidgetModule] });
beforeEach(() => {
({ fixture, dl, context } = createTestContext(TestFormComponent));
diff --git a/packages/form/src/widgets/mention/mention.widget.ts b/packages/form/widgets/mention/widget.ts
similarity index 59%
rename from packages/form/src/widgets/mention/mention.widget.ts
rename to packages/form/widgets/mention/widget.ts
index 3e1f88d725..a7db786b5d 100644
--- a/packages/form/src/widgets/mention/mention.widget.ts
+++ b/packages/form/widgets/mention/widget.ts
@@ -1,22 +1,70 @@
import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { map, tap } from 'rxjs';
+import { ControlUIWidget, SFSchemaEnum, SFValue, getData, getEnum } from '@delon/form';
import type { NzSafeAny } from 'ng-zorro-antd/core/types';
import { MentionOnSearchTypes, NzMentionComponent } from 'ng-zorro-antd/mention';
-import { SFMentionWidgetSchema } from './schema';
-import { SFValue } from '../../interface';
-import { SFSchemaEnum } from '../../schema';
-import { getData, getEnum } from '../../utils';
-import { ControlUIWidget } from '../../widget';
+import type { SFMentionWidgetSchema } from './schema';
@Component({
selector: 'sf-mention',
- templateUrl: './mention.widget.html',
+ template: `
+
+
+
+
+ `,
preserveWhitespaces: false,
encapsulation: ViewEncapsulation.None
})
export class MentionWidget extends ControlUIWidget implements OnInit {
+ static readonly KEY = 'mention';
+
@ViewChild('mentions', { static: true }) private mentionChild!: NzMentionComponent;
data: SFSchemaEnum[] = [];
i: NzSafeAny;
diff --git a/packages/form/widgets/qr-code/demo/simple.md b/packages/form/widgets/qr-code/demo/simple.md
new file mode 100644
index 0000000000..866f3d01de
--- /dev/null
+++ b/packages/form/widgets/qr-code/demo/simple.md
@@ -0,0 +1,67 @@
+---
+title:
+ zh-CN: 基础样例
+ en-US: Basic Usage
+order: 0
+---
+
+## zh-CN
+
+最简单的用法。
+
+## en-US
+
+Simplest of usage.
+
+```ts
+import { Component } from '@angular/core';
+
+import { SFSchema } from '@delon/form';
+import type { SFQrCodeWidgetSchema } from '@delon/form/widgets/qr-code';
+import { NzMessageService } from 'ng-zorro-antd/message';
+
+@Component({
+ selector: 'app-demo',
+ template: ``
+})
+export class DemoComponent {
+ schema: SFSchema = {
+ properties: {
+ base: {
+ type: 'string',
+ title: 'Base',
+ default: 'https://ng-alain.com/',
+ ui: {
+ widget: 'qr-code',
+ refresh: console.log
+ } as SFQrCodeWidgetSchema
+ },
+ icon: {
+ type: 'string',
+ title: 'With Icon',
+ default: 'https://ng-alain.com/',
+ ui: {
+ widget: 'qr-code',
+ icon: 'https://ng-alain.com/assets/logo-color.svg',
+ bordered: true
+ } as SFQrCodeWidgetSchema
+ },
+ color: {
+ type: 'string',
+ title: 'Color',
+ default: 'https://ng-alain.com/',
+ ui: {
+ widget: 'qr-code',
+ color: '#f50'
+ } as SFQrCodeWidgetSchema
+ }
+ }
+ };
+
+ constructor(private msg: NzMessageService) {}
+
+ submit(value: {}): void {
+ this.msg.success(JSON.stringify(value));
+ }
+}
+```
diff --git a/packages/form/widgets/qr-code/index.en-US.md b/packages/form/widgets/qr-code/index.en-US.md
new file mode 100644
index 0000000000..83e40a3b5a
--- /dev/null
+++ b/packages/form/widgets/qr-code/index.en-US.md
@@ -0,0 +1,28 @@
+---
+title: qr-code
+subtitle: QRCode
+type: Non-built-in widgets
+---
+
+Used when the link needs to be converted into a QR Code.
+
+## Import module
+
+Non-built-in modules, Should be import `QrCodeWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
+
+## API
+
+### ui
+
+| Property | Description | Type | Default |
+|----------|-------------|------|---------|
+| `[color]` | QR code Color | `string` | `#000` |
+| `[bgColor]` | QR code background color | `string` | `#FFFFFF` |
+| `[qrSize]` | QR code Size | `number` | `160` |
+| `[padding]` | QR code Padding | `number \| number[]` | `0` |
+| `[icon]` | Icon address in QR code | `string` | - |
+| `[iconSize]` | The size of the icon in the QR code | `number` | `40` |
+| `[bordered]` | Whether has border style | `boolean` | `true` |
+| `[status]` | QR code status | `'active'|'expired' |'loading'` | `active` |
+| `[level]` | Error Code Level | `'L'|'M'|'Q'|'H'` | `M` |
+| `(refresh)` | callback | `EventEmitter` | - |
diff --git a/packages/form/widgets/qr-code/index.ts b/packages/form/widgets/qr-code/index.ts
new file mode 100644
index 0000000000..e97ca0fae5
--- /dev/null
+++ b/packages/form/widgets/qr-code/index.ts
@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+import { NzQRCodeModule } from 'ng-zorro-antd/qr-code';
+
+import { QrCodeWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, DelonFormModule, NzQRCodeModule],
+ declarations: [QrCodeWidget]
+})
+export class QrCodeWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(QrCodeWidget.KEY, QrCodeWidget);
+ }
+}
diff --git a/packages/form/widgets/qr-code/index.zh-CN.md b/packages/form/widgets/qr-code/index.zh-CN.md
new file mode 100644
index 0000000000..32076a1edc
--- /dev/null
+++ b/packages/form/widgets/qr-code/index.zh-CN.md
@@ -0,0 +1,28 @@
+---
+title: qr-code
+subtitle: 二维码
+type: Non-built-in widgets
+---
+
+当需要将链接转换成为二维码时使用。
+
+## 导入模块
+
+非内置模块,需要额外在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `QrCodeWidgetModule`。
+
+## API
+
+### ui 属性
+
+| 成员 | 说明 | 类型 | 默认值 |
+|----|----|----|-----|
+| `[color]` | 二维码颜色 | `string` | `#000` |
+| `[bgColor]` | 二维码背景颜色 | `string` | `#FFFFFF` |
+| `[qrSize]` | 二维码大小 | `number` | `160` |
+| `[padding]` | 二维码填充 | `number \| number[]` | `0` |
+| `[icon]` | 二维码中 icon 地址 | `string` | - |
+| `[iconSize]` | 二维码中 icon 大小 | `number` | `40` |
+| `[bordered]` | 是否有边框 | `boolean` | `true` |
+| `[status]` | 二维码状态 | `'active'|'expired' |'loading'` | `active` |
+| `[level]` | 二维码容错等级 | `'L'|'M'|'Q'|'H'` | `M` |
+| `(refresh)` | 点击"点击刷新"的回调 | `EventEmitter` | - |
diff --git a/packages/form/widgets/qr-code/ng-package.json b/packages/form/widgets/qr-code/ng-package.json
new file mode 100644
index 0000000000..3b78722325
--- /dev/null
+++ b/packages/form/widgets/qr-code/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-qr-code",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/widgets/qr-code/schema.ts b/packages/form/widgets/qr-code/schema.ts
new file mode 100644
index 0000000000..49be6274ba
--- /dev/null
+++ b/packages/form/widgets/qr-code/schema.ts
@@ -0,0 +1,25 @@
+import type { SFUISchemaItem } from '@delon/form';
+import type { ERROR_LEVEL_MAP } from 'ng-zorro-antd/qr-code/qrcode';
+
+export interface SFQrCodeWidgetSchema extends SFUISchemaItem {
+ /** QR code Padding */
+ padding?: number;
+ /** QR code Color */
+ color?: string;
+ /** QR code background color */
+ bgColor?: string;
+ /** QR code Size */
+ qrSize?: number;
+ /** Icon address in QR code */
+ icon?: string;
+ /** The size of the icon in the QR code */
+ iconSize?: number;
+ /** Whether has border style */
+ bordered?: boolean;
+ /** QR code status */
+ status?: 'active' | 'expired' | 'loading';
+ /** Error Code Level */
+ level?: keyof typeof ERROR_LEVEL_MAP;
+ /** Callback */
+ refresh?: (qr: string) => void;
+}
diff --git a/packages/form/widgets/qr-code/widget.spec.ts b/packages/form/widgets/qr-code/widget.spec.ts
new file mode 100644
index 0000000000..6f348610a9
--- /dev/null
+++ b/packages/form/widgets/qr-code/widget.spec.ts
@@ -0,0 +1,37 @@
+import { DebugElement } from '@angular/core';
+import { ComponentFixture, fakeAsync } from '@angular/core/testing';
+
+import { SFSchema } from '@delon/form';
+import { createTestContext } from '@delon/testing';
+
+import { QrCodeWidgetModule, SFQrCodeWidgetSchema } from './index';
+import { configureSFTestSuite, SFPage, TestFormComponent } from '../../spec/base.spec';
+
+describe('form: widget: qr-code', () => {
+ let fixture: ComponentFixture;
+ let dl: DebugElement;
+ let context: TestFormComponent;
+ let page: SFPage;
+
+ configureSFTestSuite({ imports: [QrCodeWidgetModule] });
+
+ beforeEach(() => {
+ ({ fixture, dl, context } = createTestContext(TestFormComponent));
+ page = new SFPage(context.comp);
+ page.cleanOverlay().prop(dl, context, fixture);
+ });
+
+ it('should be working', fakeAsync(() => {
+ const s: SFSchema = {
+ properties: {
+ a: {
+ type: 'string',
+ ui: {
+ widget: 'qr-code'
+ } as SFQrCodeWidgetSchema
+ }
+ }
+ };
+ page.newSchema(s).getEl('canvas');
+ }));
+});
diff --git a/packages/form/widgets/qr-code/widget.ts b/packages/form/widgets/qr-code/widget.ts
new file mode 100644
index 0000000000..db3c94cb96
--- /dev/null
+++ b/packages/form/widgets/qr-code/widget.ts
@@ -0,0 +1,41 @@
+import { Component, ViewEncapsulation } from '@angular/core';
+
+import { ControlUIWidget } from '@delon/form';
+
+import type { SFQrCodeWidgetSchema } from './schema';
+
+@Component({
+ selector: 'sf-qr-code',
+ template: `
+
+ `,
+ preserveWhitespaces: false,
+ encapsulation: ViewEncapsulation.None
+})
+export class QrCodeWidget extends ControlUIWidget {
+ static readonly KEY = 'qr-code';
+
+ refresh(qr: string): void {
+ this.setValue(qr);
+ if (this.ui.refresh) this.ui.refresh(qr);
+ }
+}
diff --git a/packages/form/src/widgets/rate/demo/simple.md b/packages/form/widgets/rate/demo/simple.md
similarity index 90%
rename from packages/form/src/widgets/rate/demo/simple.md
rename to packages/form/widgets/rate/demo/simple.md
index 2da2d71114..b30b278dab 100644
--- a/packages/form/src/widgets/rate/demo/simple.md
+++ b/packages/form/widgets/rate/demo/simple.md
@@ -15,7 +15,8 @@ Simplest of usage.
```ts
import { Component } from '@angular/core';
-import { SFRateWidgetSchema, SFSchema } from '@delon/form';
+import { SFSchema } from '@delon/form';
+import type { SFRateWidgetSchema } from '@delon/form/widgets/rate';
import { NzMessageService } from 'ng-zorro-antd/message';
@Component({
diff --git a/packages/form/src/widgets/rate/index.en-US.md b/packages/form/widgets/rate/index.en-US.md
similarity index 75%
rename from packages/form/src/widgets/rate/index.en-US.md
rename to packages/form/widgets/rate/index.en-US.md
index 1effb25674..0dbe11ca9c 100644
--- a/packages/form/src/widgets/rate/index.en-US.md
+++ b/packages/form/widgets/rate/index.en-US.md
@@ -1,11 +1,15 @@
---
title: rate
subtitle: Rate
-type: Widgets
+type: Non-built-in widgets
---
A quick rating operation on something.
+## Import module
+
+Non-built-in modules, Should be import `RateWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
+
## API
### schema
diff --git a/packages/form/widgets/rate/index.ts b/packages/form/widgets/rate/index.ts
new file mode 100644
index 0000000000..89b91dd35f
--- /dev/null
+++ b/packages/form/widgets/rate/index.ts
@@ -0,0 +1,21 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+import { NzRateModule } from 'ng-zorro-antd/rate';
+
+import { RateWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, DelonFormModule, NzRateModule, CommonModule],
+ declarations: [RateWidget]
+})
+export class RateWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(RateWidget.KEY, RateWidget);
+ }
+}
diff --git a/packages/form/src/widgets/rate/index.zh-CN.md b/packages/form/widgets/rate/index.zh-CN.md
similarity index 75%
rename from packages/form/src/widgets/rate/index.zh-CN.md
rename to packages/form/widgets/rate/index.zh-CN.md
index 7e917278f4..911776498c 100644
--- a/packages/form/src/widgets/rate/index.zh-CN.md
+++ b/packages/form/widgets/rate/index.zh-CN.md
@@ -1,11 +1,15 @@
---
title: rate
subtitle: 评分
-type: Widgets
+type: Non-built-in widgets
---
对评价进行展示,对事物进行快速的评级操作。
+## 导入模块
+
+非内置模块,需要额外在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `RateWidgetModule`。
+
## API
### schema 属性
diff --git a/packages/form/widgets/rate/ng-package.json b/packages/form/widgets/rate/ng-package.json
new file mode 100644
index 0000000000..b9b116ea3a
--- /dev/null
+++ b/packages/form/widgets/rate/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-rate",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/src/widgets/rate/schema.ts b/packages/form/widgets/rate/schema.ts
similarity index 89%
rename from packages/form/src/widgets/rate/schema.ts
rename to packages/form/widgets/rate/schema.ts
index 6d5f7d6274..47f14d3d08 100644
--- a/packages/form/src/widgets/rate/schema.ts
+++ b/packages/form/widgets/rate/schema.ts
@@ -1,4 +1,4 @@
-import { SFUISchemaItem } from '../../schema/ui';
+import type { SFUISchemaItem } from '@delon/form';
export interface SFRateWidgetSchema extends SFUISchemaItem {
/**
diff --git a/packages/form/src/widgets/rate/rate.widget.spec.ts b/packages/form/widgets/rate/widget.spec.ts
similarity index 91%
rename from packages/form/src/widgets/rate/rate.widget.spec.ts
rename to packages/form/widgets/rate/widget.spec.ts
index 847fbf6a36..d992fefa0b 100644
--- a/packages/form/src/widgets/rate/rate.widget.spec.ts
+++ b/packages/form/widgets/rate/widget.spec.ts
@@ -3,7 +3,8 @@ import { ComponentFixture, fakeAsync } from '@angular/core/testing';
import { createTestContext } from '@delon/testing';
-import { configureSFTestSuite, SFPage, TestFormComponent } from '../../../spec/base.spec';
+import { RateWidgetModule } from './index';
+import { configureSFTestSuite, SFPage, TestFormComponent } from '../../spec/base.spec';
describe('form: widget: rate', () => {
let fixture: ComponentFixture;
@@ -12,7 +13,7 @@ describe('form: widget: rate', () => {
let page: SFPage;
const widget = 'rate';
- configureSFTestSuite();
+ configureSFTestSuite({ imports: [RateWidgetModule] });
beforeEach(() => {
({ fixture, dl, context } = createTestContext(TestFormComponent));
diff --git a/packages/form/src/widgets/rate/rate.widget.ts b/packages/form/widgets/rate/widget.ts
similarity index 52%
rename from packages/form/src/widgets/rate/rate.widget.ts
rename to packages/form/widgets/rate/widget.ts
index fd4e565b91..81d6191d5f 100644
--- a/packages/form/src/widgets/rate/rate.widget.ts
+++ b/packages/form/widgets/rate/widget.ts
@@ -1,16 +1,37 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
-import { SFRateWidgetSchema } from './schema';
-import { toBool } from '../../utils';
-import { ControlUIWidget } from '../../widget';
+import { ControlUIWidget, toBool } from '@delon/form';
+
+import type { SFRateWidgetSchema } from './schema';
@Component({
selector: 'sf-rate',
- templateUrl: './rate.widget.html',
+ template: `
+
+ {{ text }}
+ `,
preserveWhitespaces: false,
encapsulation: ViewEncapsulation.None
})
export class RateWidget extends ControlUIWidget implements OnInit {
+ static readonly KEY = 'rate';
+
count!: number;
allowHalf!: boolean;
allowClear!: boolean;
diff --git a/packages/form/widgets/segmented/demo/simple.md b/packages/form/widgets/segmented/demo/simple.md
new file mode 100644
index 0000000000..9afa849841
--- /dev/null
+++ b/packages/form/widgets/segmented/demo/simple.md
@@ -0,0 +1,65 @@
+---
+title:
+ zh-CN: 基础样例
+ en-US: Basic Usage
+order: 0
+---
+
+## zh-CN
+
+最简单的用法。
+
+## en-US
+
+Simplest of usage.
+
+```ts
+import { Component } from '@angular/core';
+import { delay, of } from 'rxjs';
+
+import { SFSchema } from '@delon/form';
+import { SFSegmentedWidgetSchema, SegmentedWidget } from '@delon/form/widgets/segmented';
+import { NzMessageService } from 'ng-zorro-antd/message';
+import { NzSegmentedOptions } from 'ng-zorro-antd/segmented';
+
+@Component({
+ selector: 'app-demo',
+ template: ``
+})
+export class DemoComponent {
+ schema: SFSchema = {
+ properties: {
+ base: {
+ type: 'string',
+ title: 'Base',
+ default: 2,
+ enum: ['Daily', 'Weekly', 'Monthly', 'Quarterly', 'Yearly'],
+ ui: {
+ widget: SegmentedWidget.KEY,
+ valueChange: console.log
+ } as SFSegmentedWidgetSchema
+ },
+ asyncData: {
+ type: 'string',
+ title: 'Async Data',
+ ui: {
+ widget: SegmentedWidget.KEY,
+ asyncData: () =>
+ of([
+ { label: 'Label1', value: 'a' },
+ { label: 'Label2', value: 'b' },
+ { label: 'Label3', value: 'c', disabled: true }
+ ] as NzSegmentedOptions).pipe(delay(1000)),
+ valueChange: console.log
+ } as SFSegmentedWidgetSchema
+ }
+ }
+ };
+
+ constructor(private msg: NzMessageService) {}
+
+ submit(value: {}): void {
+ this.msg.success(JSON.stringify(value));
+ }
+}
+```
diff --git a/packages/form/widgets/segmented/index.en-US.md b/packages/form/widgets/segmented/index.en-US.md
new file mode 100644
index 0000000000..a688d37a56
--- /dev/null
+++ b/packages/form/widgets/segmented/index.en-US.md
@@ -0,0 +1,22 @@
+---
+title: segmented
+subtitle: Segmented
+type: Non-built-in widgets
+---
+
+- When displaying multiple options and user can select a single option;
+- When switching the selected option, the content of the associated area changes.
+
+## Import module
+
+Non-built-in modules, Should be import `SegmentedWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
+
+## API
+
+### ui
+
+| Property | Description | Type | Default |
+|----------|-------------|------|---------|
+| `[block]` | Option to fit width to its parent\'s width | `boolean` | false | |
+| `[asyncData]` | Set children optional | `() => Observable` | - | |
+| `(valueChange)` | Emits when index of the currently selected option changes | `(data: { index: number; item: SFValue }) => void` | - | |
diff --git a/packages/form/widgets/segmented/index.ts b/packages/form/widgets/segmented/index.ts
new file mode 100644
index 0000000000..97019ccd83
--- /dev/null
+++ b/packages/form/widgets/segmented/index.ts
@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+import { NzSegmentedModule } from 'ng-zorro-antd/segmented';
+
+import { SegmentedWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, DelonFormModule, NzSegmentedModule],
+ declarations: [SegmentedWidget]
+})
+export class SegmentedWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(SegmentedWidget.KEY, SegmentedWidget);
+ }
+}
diff --git a/packages/form/widgets/segmented/index.zh-CN.md b/packages/form/widgets/segmented/index.zh-CN.md
new file mode 100644
index 0000000000..a7c765d643
--- /dev/null
+++ b/packages/form/widgets/segmented/index.zh-CN.md
@@ -0,0 +1,22 @@
+---
+title: segmented
+subtitle: 分段控制器
+type: Non-built-in widgets
+---
+
+- 用于展示多个选项并允许用户选择其中单个选项;
+- 当切换选中选项时,关联区域的内容会发生变化。
+
+## 导入模块
+
+非内置模块,需要额外在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `SegmentedWidgetModule`。
+
+## API
+
+### ui 属性
+
+| 成员 | 说明 | 类型 | 默认值 |
+|----|----|----|-----|
+| `[block]` | 将宽度调整为父元素宽度的选项 | `boolean` | false | |
+| `[asyncData]` | 异步数据 | `() => Observable` | - | |
+| `(valueChange)` | 当前选中项目变化时触发回调 | `(data: { index: number; item: SFValue }) => void` | - | |
diff --git a/packages/form/widgets/segmented/ng-package.json b/packages/form/widgets/segmented/ng-package.json
new file mode 100644
index 0000000000..ec57a9fa30
--- /dev/null
+++ b/packages/form/widgets/segmented/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-color",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/widgets/segmented/schema.ts b/packages/form/widgets/segmented/schema.ts
new file mode 100644
index 0000000000..897c7539b6
--- /dev/null
+++ b/packages/form/widgets/segmented/schema.ts
@@ -0,0 +1,21 @@
+import type { TemplateRef } from '@angular/core';
+import type { Observable } from 'rxjs';
+
+import type { SFUISchemaItem, SFValue } from '@delon/form';
+import type { NzSegmentedOption, NzSegmentedOptions } from 'ng-zorro-antd/segmented';
+
+export interface SFSegmentedWidgetSchema extends SFUISchemaItem {
+ /**
+ * 异步数据源
+ */
+ asyncData?: () => Observable;
+ /**
+ * Option to fit width to its parent's width
+ */
+ block?: boolean;
+ labelTemplate?: TemplateRef<{ $implicit: NzSegmentedOption; index: number }> | null;
+ /**
+ * Emits when index of the currently selected option changes
+ */
+ valueChange?: (data: { index: number; item: SFValue }) => void;
+}
diff --git a/packages/form/widgets/segmented/widget.spec.ts b/packages/form/widgets/segmented/widget.spec.ts
new file mode 100644
index 0000000000..2a503c199c
--- /dev/null
+++ b/packages/form/widgets/segmented/widget.spec.ts
@@ -0,0 +1,42 @@
+import { DebugElement } from '@angular/core';
+import { ComponentFixture, fakeAsync } from '@angular/core/testing';
+
+import { SFSchema } from '@delon/form';
+import { createTestContext } from '@delon/testing';
+
+import { SegmentedWidgetModule, SFSegmentedWidgetSchema } from './index';
+import { configureSFTestSuite, SFPage, TestFormComponent } from '../../spec/base.spec';
+
+describe('form: widget: segmented', () => {
+ let fixture: ComponentFixture;
+ let dl: DebugElement;
+ let context: TestFormComponent;
+ let page: SFPage;
+
+ configureSFTestSuite({ imports: [SegmentedWidgetModule] });
+
+ beforeEach(() => {
+ ({ fixture, dl, context } = createTestContext(TestFormComponent));
+ page = new SFPage(context.comp);
+ page.cleanOverlay().prop(dl, context, fixture);
+ });
+
+ it('should be working', fakeAsync(() => {
+ const valueChange = jasmine.createSpy();
+ const s: SFSchema = {
+ properties: {
+ a: {
+ type: 'string',
+ enum: ['Daily', 'Weekly', 'Monthly', 'Quarterly', 'Yearly'],
+ ui: {
+ widget: 'segmented',
+ valueChange
+ } as SFSegmentedWidgetSchema
+ }
+ }
+ };
+ page.newSchema(s).typeEvent('click', '.ant-segmented-item:nth-child(2) .ant-segmented-item-label');
+ expect(page.getValue('/a')).toBe(1);
+ expect(valueChange).toHaveBeenCalled();
+ }));
+});
diff --git a/packages/form/widgets/segmented/widget.ts b/packages/form/widgets/segmented/widget.ts
new file mode 100644
index 0000000000..d97ab147bb
--- /dev/null
+++ b/packages/form/widgets/segmented/widget.ts
@@ -0,0 +1,51 @@
+import { Component, ViewEncapsulation } from '@angular/core';
+
+import { ControlUIWidget, SFValue, getData } from '@delon/form';
+import { NzSegmentedOptions } from 'ng-zorro-antd/segmented';
+
+import type { SFSegmentedWidgetSchema } from './schema';
+
+@Component({
+ selector: 'sf-segmented',
+ template: `
+
+ `,
+ preserveWhitespaces: false,
+ encapsulation: ViewEncapsulation.None
+})
+export class SegmentedWidget extends ControlUIWidget {
+ static readonly KEY = 'segmented';
+ private _list?: NzSegmentedOptions;
+ get list(): NzSegmentedOptions {
+ return this._list ?? [];
+ }
+
+ reset(value: SFValue): void {
+ getData(this.schema, this.ui, value).subscribe(list => {
+ this._list = list as NzSegmentedOptions;
+ this.detectChanges();
+ });
+ }
+
+ valueChange(index: number): void {
+ if (this.ui.valueChange) {
+ this.ui.valueChange({ index, item: this.list[index] as SFValue });
+ }
+ }
+}
diff --git a/packages/form/src/widgets/slider/demo/simple.md b/packages/form/widgets/slider/demo/simple.md
similarity index 89%
rename from packages/form/src/widgets/slider/demo/simple.md
rename to packages/form/widgets/slider/demo/simple.md
index 1edbe73ef5..a6b4d9b326 100644
--- a/packages/form/src/widgets/slider/demo/simple.md
+++ b/packages/form/widgets/slider/demo/simple.md
@@ -15,7 +15,8 @@ Simplest of usage.
```ts
import { Component } from '@angular/core';
-import { SFSchema, SFSliderWidgetSchema } from '@delon/form';
+import { SFSchema } from '@delon/form';
+import type { SFSliderWidgetSchema } from '@delon/form/widgets/slider';
import { NzMessageService } from 'ng-zorro-antd/message';
@Component({
diff --git a/packages/form/src/widgets/slider/index.en-US.md b/packages/form/widgets/slider/index.en-US.md
similarity index 85%
rename from packages/form/src/widgets/slider/index.en-US.md
rename to packages/form/widgets/slider/index.en-US.md
index 76837de082..616617be40 100644
--- a/packages/form/src/widgets/slider/index.en-US.md
+++ b/packages/form/widgets/slider/index.en-US.md
@@ -1,11 +1,15 @@
---
-title: range
+title: slider
subtitle: Slider
-type: Widgets
+type: Non-built-in widgets
---
A Slider component for displaying current value and intervals in range.
+## Import module
+
+Non-built-in modules, Should be import `SliderWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
+
## Notice
- Ingored `exclusiveMinimum`, `exclusiveMaximum`
diff --git a/packages/form/widgets/slider/index.ts b/packages/form/widgets/slider/index.ts
new file mode 100644
index 0000000000..b61dc1ee42
--- /dev/null
+++ b/packages/form/widgets/slider/index.ts
@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+import { NzSliderModule } from 'ng-zorro-antd/slider';
+
+import { SliderWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, DelonFormModule, NzSliderModule],
+ declarations: [SliderWidget]
+})
+export class SliderWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(SliderWidget.KEY, SliderWidget);
+ }
+}
diff --git a/packages/form/src/widgets/slider/index.zh-CN.md b/packages/form/widgets/slider/index.zh-CN.md
similarity index 82%
rename from packages/form/src/widgets/slider/index.zh-CN.md
rename to packages/form/widgets/slider/index.zh-CN.md
index 5527b63029..51e96a37e3 100644
--- a/packages/form/src/widgets/slider/index.zh-CN.md
+++ b/packages/form/widgets/slider/index.zh-CN.md
@@ -1,11 +1,15 @@
---
-title: range
+title: slider
subtitle: 滑动输入条
-type: Widgets
+type: Non-built-in widgets
---
滑动型输入器,展示当前值和可选范围。
+## 导入模块
+
+非内置模块,需要额外在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `SliderWidgetModule`。
+
## 注意事项
- 强制忽略 `exclusiveMinimum`、`exclusiveMaximum`
diff --git a/packages/form/widgets/slider/ng-package.json b/packages/form/widgets/slider/ng-package.json
new file mode 100644
index 0000000000..ddee7bcabf
--- /dev/null
+++ b/packages/form/widgets/slider/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-slider",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/src/widgets/slider/schema.ts b/packages/form/widgets/slider/schema.ts
similarity index 94%
rename from packages/form/src/widgets/slider/schema.ts
rename to packages/form/widgets/slider/schema.ts
index e316a843ec..3bbe805457 100644
--- a/packages/form/src/widgets/slider/schema.ts
+++ b/packages/form/widgets/slider/schema.ts
@@ -1,7 +1,6 @@
+import type { SFUISchemaItem } from '@delon/form';
import { NzMarks, NzSliderValue } from 'ng-zorro-antd/slider';
-import { SFUISchemaItem } from '../../schema/ui';
-
export interface SFSliderWidgetSchema extends SFUISchemaItem {
/**
* 当添加该属性时,启动双滑块模式
diff --git a/packages/form/src/widgets/slider/slider.widget.spec.ts b/packages/form/widgets/slider/widget.spec.ts
similarity index 93%
rename from packages/form/src/widgets/slider/slider.widget.spec.ts
rename to packages/form/widgets/slider/widget.spec.ts
index 190fe63969..bef7168123 100644
--- a/packages/form/src/widgets/slider/slider.widget.spec.ts
+++ b/packages/form/widgets/slider/widget.spec.ts
@@ -1,13 +1,14 @@
import { DebugElement } from '@angular/core';
import { ComponentFixture, fakeAsync } from '@angular/core/testing';
+import { SFSchema } from '@delon/form';
import { createTestContext } from '@delon/testing';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzSliderComponent } from 'ng-zorro-antd/slider';
-import { SliderWidget } from './slider.widget';
-import { configureSFTestSuite, SFPage, TestFormComponent } from '../../../spec/base.spec';
-import { SFSchema } from '../../../src/schema/index';
+import { SliderWidgetModule } from './index';
+import { SliderWidget } from './widget';
+import { configureSFTestSuite, SFPage, TestFormComponent } from '../../spec/base.spec';
describe('form: widget: slider', () => {
let fixture: ComponentFixture;
@@ -16,7 +17,7 @@ describe('form: widget: slider', () => {
let page: SFPage;
const widget = 'slider';
- configureSFTestSuite();
+ configureSFTestSuite({ imports: [SliderWidgetModule] });
beforeEach(() => {
({ fixture, dl, context } = createTestContext(TestFormComponent));
diff --git a/packages/form/src/widgets/slider/slider.widget.ts b/packages/form/widgets/slider/widget.ts
similarity index 59%
rename from packages/form/src/widgets/slider/slider.widget.ts
rename to packages/form/widgets/slider/widget.ts
index 459b4a8839..ba4d8910ea 100644
--- a/packages/form/src/widgets/slider/slider.widget.ts
+++ b/packages/form/widgets/slider/widget.ts
@@ -1,17 +1,42 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
+import { ControlUIWidget } from '@delon/form';
import { NzMarks, NzSliderValue } from 'ng-zorro-antd/slider';
-import { SFSliderWidgetSchema } from './schema';
-import { ControlUIWidget } from '../../widget';
+import type { SFSliderWidgetSchema } from './schema';
@Component({
selector: 'sf-slider',
- templateUrl: './slider.widget.html',
+ template: `
+
+ `,
preserveWhitespaces: false,
encapsulation: ViewEncapsulation.None
})
export class SliderWidget extends ControlUIWidget implements OnInit {
+ static readonly KEY = 'slider';
+
min!: number;
max!: number;
step!: number;
diff --git a/packages/form/src/widgets/tag/demo/simple.md b/packages/form/widgets/tag/demo/simple.md
similarity index 93%
rename from packages/form/src/widgets/tag/demo/simple.md
rename to packages/form/widgets/tag/demo/simple.md
index 0ee04cce70..6fcfa18bb7 100644
--- a/packages/form/src/widgets/tag/demo/simple.md
+++ b/packages/form/widgets/tag/demo/simple.md
@@ -15,7 +15,8 @@ Simplest of usage.
```ts
import { Component } from '@angular/core';
-import { SFIcon, SFSchema, SFTagWidgetSchema } from '@delon/form';
+import { SFIcon, SFSchema } from '@delon/form';
+import type { SFTagWidgetSchema } from '@delon/form/widgets/tag';
import { NzMessageService } from 'ng-zorro-antd/message';
import { of, delay } from 'rxjs';
diff --git a/packages/form/src/widgets/tag/index.en-US.md b/packages/form/widgets/tag/index.en-US.md
similarity index 75%
rename from packages/form/src/widgets/tag/index.en-US.md
rename to packages/form/widgets/tag/index.en-US.md
index fc0e5523fe..8514e22c8a 100644
--- a/packages/form/src/widgets/tag/index.en-US.md
+++ b/packages/form/widgets/tag/index.en-US.md
@@ -1,11 +1,15 @@
---
title: tag
subtitle: Tag
-type: Widgets
+type: Non-built-in widgets
---
Tag for categorizing or markup, **Notice:** Just only supported `checkable` tag mode.
+## Import module
+
+Non-built-in modules, Should be import `TagWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
+
## API
### schema
diff --git a/packages/form/widgets/tag/index.ts b/packages/form/widgets/tag/index.ts
new file mode 100644
index 0000000000..be4562e563
--- /dev/null
+++ b/packages/form/widgets/tag/index.ts
@@ -0,0 +1,22 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+import { NzIconModule } from 'ng-zorro-antd/icon';
+import { NzTagModule } from 'ng-zorro-antd/tag';
+
+import { TagWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, DelonFormModule, NzTagModule, NzIconModule, CommonModule],
+ declarations: [TagWidget]
+})
+export class TagWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(TagWidget.KEY, TagWidget);
+ }
+}
diff --git a/packages/form/src/widgets/tag/index.zh-CN.md b/packages/form/widgets/tag/index.zh-CN.md
similarity index 75%
rename from packages/form/src/widgets/tag/index.zh-CN.md
rename to packages/form/widgets/tag/index.zh-CN.md
index 648512508c..d96a7329f5 100644
--- a/packages/form/src/widgets/tag/index.zh-CN.md
+++ b/packages/form/widgets/tag/index.zh-CN.md
@@ -1,11 +1,15 @@
---
title: tag
subtitle: 标签
-type: Widgets
+type: Non-built-in widgets
---
进行标记和分类的小标签,**注:** 只支持 `checkable` 标签模式。
+## 导入模块
+
+非内置模块,需要额外在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `TagWidgetModule`。
+
## API
### schema 属性
diff --git a/packages/form/widgets/tag/ng-package.json b/packages/form/widgets/tag/ng-package.json
new file mode 100644
index 0000000000..6914a665fc
--- /dev/null
+++ b/packages/form/widgets/tag/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-tag",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/src/widgets/tag/schema.ts b/packages/form/widgets/tag/schema.ts
similarity index 83%
rename from packages/form/src/widgets/tag/schema.ts
rename to packages/form/widgets/tag/schema.ts
index 46904ffb83..b4618e7b01 100644
--- a/packages/form/src/widgets/tag/schema.ts
+++ b/packages/form/widgets/tag/schema.ts
@@ -1,7 +1,6 @@
import { Observable } from 'rxjs';
-import { SFSchemaEnumType } from '../../schema';
-import { SFUISchemaItem } from '../../schema/ui';
+import type { SFSchemaEnumType, SFUISchemaItem } from '@delon/form';
export interface SFTagWidgetSchema extends SFUISchemaItem {
/**
diff --git a/packages/form/src/widgets/tag/tag.widget.spec.ts b/packages/form/widgets/tag/widget.spec.ts
similarity index 96%
rename from packages/form/src/widgets/tag/tag.widget.spec.ts
rename to packages/form/widgets/tag/widget.spec.ts
index 2939caf4b4..6d87d9fe1a 100644
--- a/packages/form/src/widgets/tag/tag.widget.spec.ts
+++ b/packages/form/widgets/tag/widget.spec.ts
@@ -1,12 +1,13 @@
import { DebugElement } from '@angular/core';
import { ComponentFixture, fakeAsync } from '@angular/core/testing';
+import { SFSchema } from '@delon/form';
import { createTestContext } from '@delon/testing';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzTagComponent } from 'ng-zorro-antd/tag';
-import { configureSFTestSuite, SFPage, TestFormComponent } from '../../../spec/base.spec';
-import { SFSchema } from '../../../src/schema/index';
+import { TagWidgetModule } from './index';
+import { configureSFTestSuite, SFPage, TestFormComponent } from '../../spec/base.spec';
describe('form: widget: tag', () => {
let fixture: ComponentFixture;
@@ -14,7 +15,7 @@ describe('form: widget: tag', () => {
let context: TestFormComponent;
let page: SFPage;
- configureSFTestSuite();
+ configureSFTestSuite({ imports: [TagWidgetModule] });
beforeEach(() => {
({ fixture, dl, context } = createTestContext(TestFormComponent));
diff --git a/packages/form/widgets/tag/widget.ts b/packages/form/widgets/tag/widget.ts
new file mode 100644
index 0000000000..0aa379fbc3
--- /dev/null
+++ b/packages/form/widgets/tag/widget.ts
@@ -0,0 +1,77 @@
+import { Component, ViewEncapsulation } from '@angular/core';
+
+import { ControlUIWidget, SFSchemaEnum, SFValue, getData } from '@delon/form';
+
+import type { SFTagWidgetSchema } from './schema';
+
+@Component({
+ selector: 'sf-tag',
+ template: `
+
+
+
+
+
+
+
+ {{ i.label }}
+
+
+
+
+ `,
+ preserveWhitespaces: false,
+ encapsulation: ViewEncapsulation.None
+})
+export class TagWidget extends ControlUIWidget {
+ static readonly KEY = 'tag';
+
+ data: SFSchemaEnum[] = [];
+
+ reset(value: SFValue): void {
+ getData(this.schema, this.ui, value).subscribe(list => {
+ this.data = list;
+ this.detectChanges();
+ });
+ }
+
+ onChange(item: SFSchemaEnum): void {
+ item.checked = !item.checked;
+ this.updateValue();
+ if (this.ui.checkedChange) {
+ this.ui.checkedChange(item.checked);
+ }
+ }
+
+ _close(e: MouseEvent): void {
+ if (this.ui.onClose) this.ui.onClose(e);
+ }
+
+ private updateValue(): void {
+ this.formProperty.setValue(
+ this.data.filter(w => w.checked).map(i => i.value),
+ false
+ );
+ }
+}
diff --git a/packages/form/src/widgets/time/demo/simple.md b/packages/form/widgets/time/demo/simple.md
similarity index 90%
rename from packages/form/src/widgets/time/demo/simple.md
rename to packages/form/widgets/time/demo/simple.md
index e0d0e59f40..cc0fcd7ce5 100644
--- a/packages/form/src/widgets/time/demo/simple.md
+++ b/packages/form/widgets/time/demo/simple.md
@@ -15,12 +15,13 @@ Simplest of usage.
```ts
import { Component } from '@angular/core';
-import { SFSchema, SFTimeWidgetSchema } from '@delon/form';
+import { SFSchema } from '@delon/form';
+import type { SFTimeWidgetSchema } from '@delon/form/widgets/time';
import { NzMessageService } from 'ng-zorro-antd/message';
@Component({
selector: 'app-demo',
- template: ` `,
+ template: ` `,
})
export class DemoComponent {
schema: SFSchema = {
diff --git a/packages/form/src/widgets/time/index.en-US.md b/packages/form/widgets/time/index.en-US.md
similarity index 92%
rename from packages/form/src/widgets/time/index.en-US.md
rename to packages/form/widgets/time/index.en-US.md
index 5254e21128..0f0d03a471 100644
--- a/packages/form/src/widgets/time/index.en-US.md
+++ b/packages/form/widgets/time/index.en-US.md
@@ -1,11 +1,15 @@
---
title: time
subtitle: Time
-type: Widgets
+type: Non-built-in widgets
---
To select/input a time.
+## Import module
+
+Non-built-in modules, Should be import `TimeWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
+
## Notice
- Format is divided into two types: **Data format** means form data, **Display format** means display data ([nzFormat](https://ng.ant.design/components/time-picker/en#api))
diff --git a/packages/form/widgets/time/index.ts b/packages/form/widgets/time/index.ts
new file mode 100644
index 0000000000..c3ce18dec0
--- /dev/null
+++ b/packages/form/widgets/time/index.ts
@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+import { NzTimePickerModule } from 'ng-zorro-antd/time-picker';
+
+import { TimeWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, DelonFormModule, NzTimePickerModule],
+ declarations: [TimeWidget]
+})
+export class TimeWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(TimeWidget.KEY, TimeWidget);
+ }
+}
diff --git a/packages/form/src/widgets/time/index.zh-CN.md b/packages/form/widgets/time/index.zh-CN.md
similarity index 92%
rename from packages/form/src/widgets/time/index.zh-CN.md
rename to packages/form/widgets/time/index.zh-CN.md
index 993dd7c68b..fb7bca0c70 100644
--- a/packages/form/src/widgets/time/index.zh-CN.md
+++ b/packages/form/widgets/time/index.zh-CN.md
@@ -1,11 +1,15 @@
---
title: time
subtitle: 时间
-type: Widgets
+type: Non-built-in widgets
---
输入或选择时间的控件。
+## 导入模块
+
+非内置模块,需要额外在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `TimeWidgetModule`。
+
## 注意事项
- 格式化分为:**数据格式化**表示表单数据和**显示格式化**显示数据(等同 [nzFormat](https://ng.ant.design/components/time-picker/zh#api) 值)
diff --git a/packages/form/widgets/time/ng-package.json b/packages/form/widgets/time/ng-package.json
new file mode 100644
index 0000000000..98ee820f87
--- /dev/null
+++ b/packages/form/widgets/time/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-time",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/src/widgets/time/schema.ts b/packages/form/widgets/time/schema.ts
similarity index 97%
rename from packages/form/src/widgets/time/schema.ts
rename to packages/form/widgets/time/schema.ts
index 336defd47a..f39c8df497 100644
--- a/packages/form/src/widgets/time/schema.ts
+++ b/packages/form/widgets/time/schema.ts
@@ -1,4 +1,4 @@
-import { SFDLSSize, SFUISchemaItem } from '../../schema/ui';
+import type { SFDLSSize, SFUISchemaItem } from '@delon/form';
export interface SFTimeWidgetSchema extends SFUISchemaItem {
size?: SFDLSSize;
diff --git a/packages/form/src/widgets/time/time.widget.spec.ts b/packages/form/widgets/time/widget.spec.ts
similarity index 95%
rename from packages/form/src/widgets/time/time.widget.spec.ts
rename to packages/form/widgets/time/widget.spec.ts
index 4d07cdd400..5eb051c59e 100644
--- a/packages/form/src/widgets/time/time.widget.spec.ts
+++ b/packages/form/widgets/time/widget.spec.ts
@@ -3,11 +3,12 @@ import { ComponentFixture } from '@angular/core/testing';
import { format } from 'date-fns';
+import type { SFSchema } from '@delon/form';
import { createTestContext } from '@delon/testing';
-import { TimeWidget } from './time.widget';
-import { configureSFTestSuite, SFPage, TestFormComponent } from '../../../spec/base.spec';
-import { SFSchema } from '../../../src/schema/index';
+import { TimeWidgetModule } from './index';
+import { TimeWidget } from './widget';
+import { configureSFTestSuite, SFPage, TestFormComponent } from '../../spec/base.spec';
const FORMAT = 'yyyy-MM-dd HH:mm:ss';
@@ -18,7 +19,7 @@ describe('form: widget: time', () => {
let dl: DebugElement;
const widget = 'time';
- configureSFTestSuite();
+ configureSFTestSuite({ imports: [TimeWidgetModule] });
beforeEach(() => {
({ fixture, dl, context } = createTestContext(TestFormComponent));
diff --git a/packages/form/src/widgets/time/time.widget.ts b/packages/form/widgets/time/widget.ts
similarity index 64%
rename from packages/form/src/widgets/time/time.widget.ts
rename to packages/form/widgets/time/widget.ts
index e3cfbd59c8..057d05ac10 100644
--- a/packages/form/src/widgets/time/time.widget.ts
+++ b/packages/form/widgets/time/widget.ts
@@ -2,20 +2,52 @@ import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { format } from 'date-fns';
+import { ControlUIWidget, SFValue, toBool } from '@delon/form';
import type { NzSafeAny } from 'ng-zorro-antd/core/types';
-import { SFTimeWidgetSchema } from './schema';
-import { SFValue } from '../../interface';
-import { toBool } from '../../utils';
-import { ControlUIWidget } from '../../widget';
+import type { SFTimeWidgetSchema } from './schema';
@Component({
selector: 'sf-time',
- templateUrl: './time.widget.html',
+ template: `
+
+ `,
preserveWhitespaces: false,
encapsulation: ViewEncapsulation.None
})
export class TimeWidget extends ControlUIWidget implements OnInit {
+ static readonly KEY = 'time';
+
private valueFormat: string | undefined;
displayValue: Date | null = null;
i: NzSafeAny;
diff --git a/packages/form/src/widgets/transfer/demo/simple.md b/packages/form/widgets/transfer/demo/simple.md
similarity index 93%
rename from packages/form/src/widgets/transfer/demo/simple.md
rename to packages/form/widgets/transfer/demo/simple.md
index 46424162df..7f431602ec 100644
--- a/packages/form/src/widgets/transfer/demo/simple.md
+++ b/packages/form/widgets/transfer/demo/simple.md
@@ -15,7 +15,8 @@ Simplest of usage.
```ts
import { Component } from '@angular/core';
-import { SFSchema, SFTransferWidgetSchema } from '@delon/form';
+import { SFSchema } from '@delon/form';
+import { SFTransferWidgetSchema } from '@delon/form/widgets/transfer';
import { NzMessageService } from 'ng-zorro-antd/message';
import { of, delay } from 'rxjs';
diff --git a/packages/form/src/widgets/transfer/index.en-US.md b/packages/form/widgets/transfer/index.en-US.md
similarity index 87%
rename from packages/form/src/widgets/transfer/index.en-US.md
rename to packages/form/widgets/transfer/index.en-US.md
index 85b90457c8..a345fae5cc 100644
--- a/packages/form/src/widgets/transfer/index.en-US.md
+++ b/packages/form/widgets/transfer/index.en-US.md
@@ -1,11 +1,15 @@
---
title: transfer
subtitle: Transfer
-type: Widgets
+type: Non-built-in widgets
---
Double column transfer choice box.
+## Import module
+
+Non-built-in modules, Should be import `TransferWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
+
## Note
- `default` value `direction: 'right'` indicates right column.
diff --git a/packages/form/widgets/transfer/index.ts b/packages/form/widgets/transfer/index.ts
new file mode 100644
index 0000000000..c8c388b446
--- /dev/null
+++ b/packages/form/widgets/transfer/index.ts
@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+import { NzTransferModule } from 'ng-zorro-antd/transfer';
+
+import { TransferWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, DelonFormModule, NzTransferModule],
+ declarations: [TransferWidget]
+})
+export class TransferWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(TransferWidget.KEY, TransferWidget);
+ }
+}
diff --git a/packages/form/src/widgets/transfer/index.zh-CN.md b/packages/form/widgets/transfer/index.zh-CN.md
similarity index 86%
rename from packages/form/src/widgets/transfer/index.zh-CN.md
rename to packages/form/widgets/transfer/index.zh-CN.md
index c6bed6c566..9006b7b0f6 100644
--- a/packages/form/src/widgets/transfer/index.zh-CN.md
+++ b/packages/form/widgets/transfer/index.zh-CN.md
@@ -1,11 +1,15 @@
---
title: transfer
subtitle: 穿梭框
-type: Widgets
+type: Non-built-in widgets
---
双栏穿梭选择框。
+## 导入模块
+
+非内置模块,需要额外在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `TransferWidgetModule`。
+
## 注意事项
- `default` 值被当成 `direction: 'right'` 表示右栏中
diff --git a/packages/form/widgets/transfer/ng-package.json b/packages/form/widgets/transfer/ng-package.json
new file mode 100644
index 0000000000..19483d3cc5
--- /dev/null
+++ b/packages/form/widgets/transfer/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-transfer",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/src/widgets/transfer/schema.ts b/packages/form/widgets/transfer/schema.ts
similarity index 94%
rename from packages/form/src/widgets/transfer/schema.ts
rename to packages/form/widgets/transfer/schema.ts
index f7e60aedcb..184d530c10 100644
--- a/packages/form/src/widgets/transfer/schema.ts
+++ b/packages/form/widgets/transfer/schema.ts
@@ -1,5 +1,6 @@
import { Observable } from 'rxjs';
+import type { SFSchemaEnumType, SFUISchemaItem } from '@delon/form';
import { NgStyleInterface } from 'ng-zorro-antd/core/types';
import {
TransferCanMove,
@@ -9,9 +10,6 @@ import {
TransferSelectChange
} from 'ng-zorro-antd/transfer';
-import { SFSchemaEnumType } from '../../schema';
-import { SFUISchemaItem } from '../../schema/ui';
-
export interface SFTransferWidgetSchema extends SFUISchemaItem {
/**
* 异步数据源
diff --git a/packages/form/src/widgets/transfer/transfer.widget.spec.ts b/packages/form/widgets/transfer/widget.spec.ts
similarity index 97%
rename from packages/form/src/widgets/transfer/transfer.widget.spec.ts
rename to packages/form/widgets/transfer/widget.spec.ts
index c165946adc..39cadd6688 100644
--- a/packages/form/src/widgets/transfer/transfer.widget.spec.ts
+++ b/packages/form/widgets/transfer/widget.spec.ts
@@ -2,11 +2,12 @@ import { DebugElement } from '@angular/core';
import { ComponentFixture, fakeAsync } from '@angular/core/testing';
import { of } from 'rxjs';
+import { SFSchema } from '@delon/form';
import { createTestContext } from '@delon/testing';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
-import { configureSFTestSuite, SFPage, TestFormComponent } from '../../../spec/base.spec';
-import { SFSchema } from '../../../src/schema/index';
+import { TransferWidgetModule } from './index';
+import { configureSFTestSuite, SFPage, TestFormComponent } from '../../spec/base.spec';
describe('form: widget: transfer', () => {
let fixture: ComponentFixture;
@@ -21,7 +22,7 @@ describe('form: widget: transfer', () => {
rightBtn: '.ant-transfer-operation .ant-btn:last-child'
};
- configureSFTestSuite();
+ configureSFTestSuite({ imports: [TransferWidgetModule] });
beforeEach(() => {
({ fixture, dl, context } = createTestContext(TestFormComponent));
diff --git a/packages/form/src/widgets/transfer/transfer.widget.ts b/packages/form/widgets/transfer/widget.ts
similarity index 71%
rename from packages/form/src/widgets/transfer/transfer.widget.ts
rename to packages/form/widgets/transfer/widget.ts
index 7b87eb1aaa..c64397e949 100644
--- a/packages/form/src/widgets/transfer/transfer.widget.ts
+++ b/packages/form/widgets/transfer/widget.ts
@@ -1,6 +1,7 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { Observable, of } from 'rxjs';
+import { ControlUIWidget, SFSchemaEnum, SFValue, getData } from '@delon/form';
import type { NzSafeAny } from 'ng-zorro-antd/core/types';
import {
TransferCanMove,
@@ -10,19 +11,41 @@ import {
TransferSelectChange
} from 'ng-zorro-antd/transfer';
-import { SFTransferWidgetSchema } from './schema';
-import { SFValue } from '../../interface';
-import { SFSchemaEnum } from '../../schema';
-import { getData } from '../../utils';
-import { ControlUIWidget } from '../../widget';
+import type { SFTransferWidgetSchema } from './schema';
@Component({
selector: 'sf-transfer',
- templateUrl: './transfer.widget.html',
+ template: `
+
+ `,
preserveWhitespaces: false,
encapsulation: ViewEncapsulation.None
})
export class TransferWidget extends ControlUIWidget implements OnInit {
+ static readonly KEY = 'transfer';
+
list: SFSchemaEnum[] = [];
i!: { titles: string[]; operations: string[]; itemUnit: string; itemsUnit: string };
private _data: SFSchemaEnum[] = [];
diff --git a/packages/form/src/widgets/tree-select/demo/customized-icon.md b/packages/form/widgets/tree-select/demo/customized-icon.md
similarity index 93%
rename from packages/form/src/widgets/tree-select/demo/customized-icon.md
rename to packages/form/widgets/tree-select/demo/customized-icon.md
index 391b1b9764..149bd2993d 100644
--- a/packages/form/src/widgets/tree-select/demo/customized-icon.md
+++ b/packages/form/widgets/tree-select/demo/customized-icon.md
@@ -16,7 +16,8 @@ You can customize icons for different nodes.
```ts
import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
-import { SFSchema, SFTreeSelectWidgetSchema } from '@delon/form';
+import { SFSchema } from '@delon/form';
+import type { SFTreeSelectWidgetSchema } from '@delon/form/widgets/tree-select';
import { NzTreeNode } from 'ng-zorro-antd/tree';
@Component({
diff --git a/packages/form/src/widgets/tree-select/demo/simple.md b/packages/form/widgets/tree-select/demo/simple.md
similarity index 95%
rename from packages/form/src/widgets/tree-select/demo/simple.md
rename to packages/form/widgets/tree-select/demo/simple.md
index 63bf97786d..2872430153 100644
--- a/packages/form/src/widgets/tree-select/demo/simple.md
+++ b/packages/form/widgets/tree-select/demo/simple.md
@@ -17,7 +17,8 @@ Simplest of usage.
```ts
import { Component } from '@angular/core';
-import { SFSchema, SFTreeSelectWidgetSchema } from '@delon/form';
+import { SFSchema } from '@delon/form';
+import type { SFTreeSelectWidgetSchema } from '@delon/form/widgets/tree-select';
import { NzMessageService } from 'ng-zorro-antd/message';
import { of, delay } from 'rxjs';
diff --git a/packages/form/src/widgets/tree-select/demo/virtual-scroll.md b/packages/form/widgets/tree-select/demo/virtual-scroll.md
similarity index 92%
rename from packages/form/src/widgets/tree-select/demo/virtual-scroll.md
rename to packages/form/widgets/tree-select/demo/virtual-scroll.md
index 8bc52c39ee..906ece9e9a 100644
--- a/packages/form/src/widgets/tree-select/demo/virtual-scroll.md
+++ b/packages/form/widgets/tree-select/demo/virtual-scroll.md
@@ -15,7 +15,8 @@ Set `virtualHeight` to enable virtual scroll.
```ts
import { Component } from '@angular/core';
-import { SFSchema, SFTreeSelectWidgetSchema } from '@delon/form';
+import { SFSchema } from '@delon/form';
+import type { SFTreeSelectWidgetSchema } from '@delon/form/widgets/tree-select';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzTreeNodeOptions } from 'ng-zorro-antd/tree';
diff --git a/packages/form/src/widgets/tree-select/index.en-US.md b/packages/form/widgets/tree-select/index.en-US.md
similarity index 93%
rename from packages/form/src/widgets/tree-select/index.en-US.md
rename to packages/form/widgets/tree-select/index.en-US.md
index ff8ce4fefc..3d8cb7f9bc 100644
--- a/packages/form/src/widgets/tree-select/index.en-US.md
+++ b/packages/form/widgets/tree-select/index.en-US.md
@@ -1,7 +1,7 @@
---
title: tree-select
subtitle: Tree Select
-type: Widgets
+type: Non-built-in widgets
---
Tree select widget.
@@ -10,6 +10,10 @@ Tree select widget.
- Data source of `tree-select` must have keys of `title`、`key`
+## Import module
+
+Non-built-in modules, Should be import `TreeSelectWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
+
## API
### schema
diff --git a/packages/form/widgets/tree-select/index.ts b/packages/form/widgets/tree-select/index.ts
new file mode 100644
index 0000000000..d4aaa5f4dc
--- /dev/null
+++ b/packages/form/widgets/tree-select/index.ts
@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+import { NzTreeSelectModule } from 'ng-zorro-antd/tree-select';
+
+import { TreeSelectWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, DelonFormModule, NzTreeSelectModule],
+ declarations: [TreeSelectWidget]
+})
+export class TreeSelectWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(TreeSelectWidget.KEY, TreeSelectWidget);
+ }
+}
diff --git a/packages/form/src/widgets/tree-select/index.zh-CN.md b/packages/form/widgets/tree-select/index.zh-CN.md
similarity index 92%
rename from packages/form/src/widgets/tree-select/index.zh-CN.md
rename to packages/form/widgets/tree-select/index.zh-CN.md
index 9a595be2b2..08ba1b2435 100644
--- a/packages/form/src/widgets/tree-select/index.zh-CN.md
+++ b/packages/form/widgets/tree-select/index.zh-CN.md
@@ -1,7 +1,7 @@
---
title: tree-select
subtitle: 树选择
-type: Widgets
+type: Non-built-in widgets
---
树型选择控件。
@@ -10,6 +10,10 @@ type: Widgets
- `tree-select` 的数据源必须包含 `title`、`key` 键名
+## 导入模块
+
+非内置模块,需要额外在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `TreeSelectWidgetModule`。
+
## API
### schema 属性
diff --git a/packages/form/widgets/tree-select/ng-package.json b/packages/form/widgets/tree-select/ng-package.json
new file mode 100644
index 0000000000..b3d67c2122
--- /dev/null
+++ b/packages/form/widgets/tree-select/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-tree-select",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/src/widgets/tree-select/schema.ts b/packages/form/widgets/tree-select/schema.ts
similarity index 96%
rename from packages/form/src/widgets/tree-select/schema.ts
rename to packages/form/widgets/tree-select/schema.ts
index 3542bbee7c..fc0d483738 100644
--- a/packages/form/src/widgets/tree-select/schema.ts
+++ b/packages/form/widgets/tree-select/schema.ts
@@ -1,12 +1,10 @@
import { TemplateRef } from '@angular/core';
import { Observable } from 'rxjs';
+import type { SFSchemaEnum, SFSchemaEnumType, SFUISchemaItem } from '@delon/form';
import { NzFormatEmitEvent, NzTreeNode, NzTreeNodeOptions } from 'ng-zorro-antd/core/tree';
import { NgStyleInterface, NzSizeLDSType } from 'ng-zorro-antd/core/types';
-import { SFSchemaEnum, SFSchemaEnumType } from '../../schema';
-import { SFUISchemaItem } from '../../schema/ui';
-
export interface SFTreeSelectWidgetSchema extends SFUISchemaItem {
/**
* 异步数据源
diff --git a/packages/form/src/widgets/tree-select/tree-select.widget.spec.ts b/packages/form/widgets/tree-select/widget.spec.ts
similarity index 95%
rename from packages/form/src/widgets/tree-select/tree-select.widget.spec.ts
rename to packages/form/widgets/tree-select/widget.spec.ts
index 4fa6ebf080..e766f817e2 100644
--- a/packages/form/src/widgets/tree-select/tree-select.widget.spec.ts
+++ b/packages/form/widgets/tree-select/widget.spec.ts
@@ -2,11 +2,12 @@ import { DebugElement } from '@angular/core';
import { ComponentFixture, fakeAsync } from '@angular/core/testing';
import { of } from 'rxjs';
+import { SFSchema } from '@delon/form';
import { createTestContext } from '@delon/testing';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
-import { configureSFTestSuite, SFPage, TestFormComponent } from '../../../spec/base.spec';
-import { SFSchema } from '../../../src/schema/index';
+import { TreeSelectWidgetModule } from './index';
+import { configureSFTestSuite, SFPage, TestFormComponent } from '../../spec/base.spec';
describe('form: widget: tree-select', () => {
let fixture: ComponentFixture;
@@ -15,7 +16,7 @@ describe('form: widget: tree-select', () => {
let dl: DebugElement;
const widget = 'tree-select';
- configureSFTestSuite();
+ configureSFTestSuite({ imports: [TreeSelectWidgetModule] });
beforeEach(() => {
({ fixture, dl, context } = createTestContext(TestFormComponent));
diff --git a/packages/form/src/widgets/tree-select/tree-select.widget.ts b/packages/form/widgets/tree-select/widget.ts
similarity index 50%
rename from packages/form/src/widgets/tree-select/tree-select.widget.ts
rename to packages/form/widgets/tree-select/widget.ts
index 9b67ec3ceb..9b04e5bbb7 100644
--- a/packages/form/src/widgets/tree-select/tree-select.widget.ts
+++ b/packages/form/widgets/tree-select/widget.ts
@@ -1,20 +1,61 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
+import { ControlUIWidget, SFSchemaEnum, SFValue, getData, toBool } from '@delon/form';
import { NzFormatEmitEvent, NzTreeNode } from 'ng-zorro-antd/core/tree';
-import { SFTreeSelectWidgetSchema } from './schema';
-import { SFValue } from '../../interface';
-import { SFSchemaEnum } from '../../schema';
-import { getData, toBool } from '../../utils';
-import { ControlUIWidget } from '../../widget';
+import type { SFTreeSelectWidgetSchema } from './schema';
@Component({
selector: 'sf-tree-select',
- templateUrl: './tree-select.widget.html',
+ template: `
+
+ `,
preserveWhitespaces: false,
encapsulation: ViewEncapsulation.None
})
export class TreeSelectWidget extends ControlUIWidget implements OnInit {
+ static readonly KEY = 'tree-select';
+
i!: SFTreeSelectWidgetSchema;
data: SFSchemaEnum[] = [];
asyncData = false;
diff --git a/packages/form/src/widgets/upload/demo/simple.md b/packages/form/widgets/upload/demo/simple.md
similarity index 93%
rename from packages/form/src/widgets/upload/demo/simple.md
rename to packages/form/widgets/upload/demo/simple.md
index e6d733953c..072b085b30 100644
--- a/packages/form/src/widgets/upload/demo/simple.md
+++ b/packages/form/widgets/upload/demo/simple.md
@@ -15,7 +15,8 @@ Simplest of usage.
```ts
import { Component } from '@angular/core';
-import { SFSchema, SFUploadWidgetSchema } from '@delon/form';
+import { SFSchema } from '@delon/form';
+import type { SFUploadWidgetSchema } from '@delon/form/widgets/upload';
import { NzMessageService } from 'ng-zorro-antd/message';
@Component({
diff --git a/packages/form/src/widgets/upload/index.en-US.md b/packages/form/widgets/upload/index.en-US.md
similarity index 94%
rename from packages/form/src/widgets/upload/index.en-US.md
rename to packages/form/widgets/upload/index.en-US.md
index 330c2916cd..a1c3ce0e24 100644
--- a/packages/form/src/widgets/upload/index.en-US.md
+++ b/packages/form/widgets/upload/index.en-US.md
@@ -1,11 +1,15 @@
---
title: upload
subtitle: Upload
-type: Widgets
+type: Non-built-in widgets
---
Upload file widget by select or drag.
+## Import module
+
+Non-built-in modules, Should be import `UploadWidgetModule` in [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11).
+
## Note
- **Must** set `resReName` to get correct data
diff --git a/packages/form/widgets/upload/index.ts b/packages/form/widgets/upload/index.ts
new file mode 100644
index 0000000000..45fe75f501
--- /dev/null
+++ b/packages/form/widgets/upload/index.ts
@@ -0,0 +1,23 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { DelonFormModule, WidgetRegistry } from '@delon/form';
+import { NzButtonModule } from 'ng-zorro-antd/button';
+import { NzIconModule } from 'ng-zorro-antd/icon';
+import { NzUploadModule } from 'ng-zorro-antd/upload';
+
+import { UploadWidget } from './widget';
+
+export * from './widget';
+export * from './schema';
+
+@NgModule({
+ imports: [FormsModule, CommonModule, DelonFormModule, NzUploadModule, NzIconModule, NzButtonModule],
+ declarations: [UploadWidget]
+})
+export class UploadWidgetModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(UploadWidget.KEY, UploadWidget);
+ }
+}
diff --git a/packages/form/src/widgets/upload/index.zh-CN.md b/packages/form/widgets/upload/index.zh-CN.md
similarity index 94%
rename from packages/form/src/widgets/upload/index.zh-CN.md
rename to packages/form/widgets/upload/index.zh-CN.md
index 7d29236496..504ea04e0b 100644
--- a/packages/form/src/widgets/upload/index.zh-CN.md
+++ b/packages/form/widgets/upload/index.zh-CN.md
@@ -1,11 +1,15 @@
---
title: upload
subtitle: 上传
-type: Widgets
+type: Non-built-in widgets
---
文件选择上传和拖拽上传控件。
+## 导入模块
+
+非内置模块,需要额外在 [json-schema.module.ts](https://github.com/ng-alain/ng-alain/blob/master/src/app/shared/json-schema/json-schema.module.ts#L11) 导入 `UploadWidgetModule`。
+
## 注意事项
- **务必** 指定 `resReName` 来获取正确数据
diff --git a/packages/form/widgets/upload/ng-package.json b/packages/form/widgets/upload/ng-package.json
new file mode 100644
index 0000000000..b39b5ce0f0
--- /dev/null
+++ b/packages/form/widgets/upload/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "lib": {
+ "flatModuleFile": "widgets-upload",
+ "entryFile": "index.ts"
+ }
+}
diff --git a/packages/form/src/widgets/upload/schema.ts b/packages/form/widgets/upload/schema.ts
similarity index 97%
rename from packages/form/src/widgets/upload/schema.ts
rename to packages/form/widgets/upload/schema.ts
index e3b0420a43..514aa32d26 100644
--- a/packages/form/src/widgets/upload/schema.ts
+++ b/packages/form/widgets/upload/schema.ts
@@ -1,6 +1,7 @@
import { Observable, Subscription } from 'rxjs';
-import {
+import type { SFSchemaEnumType, SFUISchemaItem } from '@delon/form';
+import type {
NzShowUploadList,
NzUploadChangeParam,
NzUploadFile,
@@ -9,9 +10,6 @@ import {
UploadFilter
} from 'ng-zorro-antd/upload';
-import { SFSchemaEnumType } from '../../schema';
-import { SFUISchemaItem } from '../../schema/ui';
-
export interface SFUploadWidgetSchema extends SFUISchemaItem {
/**
* 异步数据源
diff --git a/packages/form/src/widgets/upload/upload.widget.spec.ts b/packages/form/widgets/upload/widget.spec.ts
similarity index 97%
rename from packages/form/src/widgets/upload/upload.widget.spec.ts
rename to packages/form/widgets/upload/widget.spec.ts
index 48f7a87469..117340aa26 100644
--- a/packages/form/src/widgets/upload/upload.widget.spec.ts
+++ b/packages/form/widgets/upload/widget.spec.ts
@@ -7,8 +7,9 @@ import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzModalService } from 'ng-zorro-antd/modal';
import { NzUploadComponent } from 'ng-zorro-antd/upload';
-import { UploadWidget } from './upload.widget';
-import { configureSFTestSuite, SFPage, TestFormComponent } from '../../../spec/base.spec';
+import { UploadWidgetModule } from './index';
+import { UploadWidget } from './widget';
+import { configureSFTestSuite, SFPage, TestFormComponent } from '../../spec/base.spec';
describe('form: widget: upload', () => {
let fixture: ComponentFixture;
@@ -17,7 +18,7 @@ describe('form: widget: upload', () => {
let dl: DebugElement;
const widget = 'upload';
- configureSFTestSuite();
+ configureSFTestSuite({ imports: [UploadWidgetModule] });
beforeEach(() => {
({ fixture, dl, context } = createTestContext(TestFormComponent));
diff --git a/packages/form/src/widgets/upload/upload.widget.ts b/packages/form/widgets/upload/widget.ts
similarity index 66%
rename from packages/form/src/widgets/upload/upload.widget.ts
rename to packages/form/widgets/upload/widget.ts
index 49ecf797b5..666a6fc1a7 100644
--- a/packages/form/src/widgets/upload/upload.widget.ts
+++ b/packages/form/widgets/upload/widget.ts
@@ -1,23 +1,75 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { of } from 'rxjs';
+import { ControlUIWidget, SFValue, getData, toBool } from '@delon/form';
import { deepGet } from '@delon/util/other';
import type { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzModalService } from 'ng-zorro-antd/modal';
import { NzUploadChangeParam, NzUploadFile } from 'ng-zorro-antd/upload';
-import { SFUploadWidgetSchema } from './schema';
-import { SFValue } from '../../interface';
-import { getData, toBool } from '../../utils';
-import { ControlUIWidget } from '../../widget';
+import type { SFUploadWidgetSchema } from './schema';
@Component({
selector: 'sf-upload',
- templateUrl: './upload.widget.html',
+ template: `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
preserveWhitespaces: false,
encapsulation: ViewEncapsulation.None
})
export class UploadWidget extends ControlUIWidget implements OnInit {
+ static readonly KEY = 'upload';
+
i: NzSafeAny;
fileList: NzUploadFile[] = [];
btnType = '';
diff --git a/schematics/migration.json b/schematics/migration.json
index de75fc0db5..bb7bd15335 100644
--- a/schematics/migration.json
+++ b/schematics/migration.json
@@ -6,6 +6,11 @@
"description": "Updates NG-ALAIN to v16 [https://github.com/ng-alain/ng-alain/issues/2390]",
"factory": "./ng-update/index#updateToV16"
},
+ "migration-v17": {
+ "version": "17",
+ "description": "Updates NG-ALAIN to v17 [https://github.com/ng-alain/ng-alain/issues/2390]",
+ "factory": "./ng-update/index#updateToV17"
+ },
"ng-post-update": {
"description": "Performs cleanup after ng-update.",
"factory": "./ng-update/index#postUpdate",
diff --git a/schematics/ng-update/index.ts b/schematics/ng-update/index.ts
index af129f965b..8ef558cdd2 100644
--- a/schematics/ng-update/index.ts
+++ b/schematics/ng-update/index.ts
@@ -4,6 +4,7 @@ import { chain, Rule, SchematicContext } from '@angular-devkit/schematics';
import { ruleUpgradeData } from './upgrade-data';
import { v16Rule } from './upgrade-rules/v16';
+import { v17Rule } from './upgrade-rules/v17';
const migrations: NullableDevkitMigration[] = [];
@@ -11,6 +12,11 @@ export function updateToV16(): Rule {
return chain([v16Rule(), createMigrationSchematicRule(TargetVersion.V16, migrations, ruleUpgradeData, postUpdate)]);
}
+export function updateToV17(): Rule {
+ // , createMigrationSchematicRule(TargetVersion.V17, migrations, ruleUpgradeData, postUpdate)
+ return chain([v17Rule()]);
+}
+
/** Post-update schematic to be called when update is finished. */
export function postUpdate(context: SchematicContext, targetVersion: TargetVersion, hasFailures: boolean): void {
context.logger.info('');
diff --git a/schematics/ng-update/upgrade-rules/v17/index.spec.ts b/schematics/ng-update/upgrade-rules/v17/index.spec.ts
new file mode 100644
index 0000000000..5f4dec1796
--- /dev/null
+++ b/schematics/ng-update/upgrade-rules/v17/index.spec.ts
@@ -0,0 +1,52 @@
+import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
+
+import { createAlainApp, migrationCollection } from '../../../utils/testing';
+
+describe('Schematic: ng-update: v17Rule', () => {
+ let runner: SchematicTestRunner;
+ let tree: UnitTestTree;
+ const logs: string[] = [];
+ const jsonSchemaModulePath = '/projects/foo/src/app/shared/json-schema/json-schema.module.ts';
+
+ beforeEach(async () => {
+ ({ runner, tree } = await createAlainApp());
+ if (!tree.exists(jsonSchemaModulePath)) {
+ tree.create(
+ jsonSchemaModulePath,
+ `import { NgModule } from '@angular/core';
+ import { DelonFormModule, WidgetRegistry } from '@delon/form';
+
+ import { TestWidget } from './test/test.widget';
+ import { SharedModule } from '../shared.module';
+
+ export const SCHEMA_THIRDS_COMPONENTS = [TestWidget];
+
+ @NgModule({
+ declarations: SCHEMA_THIRDS_COMPONENTS,
+ imports: [SharedModule, DelonFormModule.forRoot()],
+ exports: SCHEMA_THIRDS_COMPONENTS
+ })
+ export class JsonSchemaModule {
+ constructor(widgetRegistry: WidgetRegistry) {
+ widgetRegistry.register(TestWidget.KEY, TestWidget);
+ }
+ }
+ `
+ );
+ }
+ });
+
+ async function runMigration(): Promise {
+ logs.length = 0;
+ runner = new SchematicTestRunner('schematics', migrationCollection);
+ runner.logger.subscribe(e => logs.push(e.message));
+ await runner.runSchematic('migration-v17', {}, tree);
+ }
+
+ it('should be working', async () => {
+ await runMigration();
+ const content = tree.readContent(jsonSchemaModulePath);
+ expect(content).toContain(`import { UploadWidgetModule } from '@delon/form/widgets/upload';`);
+ expect(content).toContain(`, UploadWidgetModule`);
+ });
+});
diff --git a/schematics/ng-update/upgrade-rules/v17/index.ts b/schematics/ng-update/upgrade-rules/v17/index.ts
new file mode 100644
index 0000000000..88bef8ba7b
--- /dev/null
+++ b/schematics/ng-update/upgrade-rules/v17/index.ts
@@ -0,0 +1,79 @@
+import { chain, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
+import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
+import { insertImport, addSymbolToNgModuleMetadata } from '@schematics/angular/utility/ast-utils';
+import { Change, InsertChange } from '@schematics/angular/utility/change';
+import * as colors from 'ansi-colors';
+
+import { DEFAULT_WORKSPACE_PATH, getSourceFile, logStart, readJSON, applyChanges } from '../../../utils';
+import { UpgradeMainVersions } from '../../../utils/versions';
+
+function qr(): Rule {
+ return (_: Tree, context: SchematicContext) => {
+ context.logger.info(
+ colors.yellow(
+ ` [qr] Will be removed in 18.0.0, please use [nz-qrcode](https://ng.ant.design/components/qr-code) instead.`
+ )
+ );
+ };
+}
+
+function autoRegisterFormWidgets(): Rule {
+ return (tree: Tree, context: SchematicContext) => {
+ const angularJson = readJSON(tree, DEFAULT_WORKSPACE_PATH);
+ const projectNames = Object.keys(angularJson.projects);
+ for (const name of projectNames) {
+ autoRegisterFormWidgetsRun(tree, name, angularJson.projects[name].sourceRoot, context);
+ }
+ };
+}
+
+function autoRegisterFormWidgetsRun(tree: Tree, name: string, sourceRoot: string, context: SchematicContext): void {
+ const modulePath = `${sourceRoot}/app/shared/json-schema/json-schema.module.ts`;
+ if (!tree.exists(modulePath)) return;
+
+ const list = [
+ { symbolName: 'AutoCompleteWidgetModule', fileName: '@delon/form/widgets/autocomplete' },
+ { symbolName: 'CascaderWidgetModule', fileName: '@delon/form/widgets/cascader' },
+ { symbolName: 'MentionWidgetModule', fileName: '@delon/form/widgets/mention' },
+ { symbolName: 'RateWidgetModule', fileName: '@delon/form/widgets/rate' },
+ { symbolName: 'SliderWidgetModule', fileName: '@delon/form/widgets/slider' },
+ { symbolName: 'TagWidgetModule', fileName: '@delon/form/widgets/tag' },
+ { symbolName: 'TimeWidgetModule', fileName: '@delon/form/widgets/time' },
+ { symbolName: 'TransferWidgetModule', fileName: '@delon/form/widgets/transfer' },
+ { symbolName: 'TreeSelectWidgetModule', fileName: '@delon/form/widgets/tree-select' },
+ { symbolName: 'UploadWidgetModule', fileName: '@delon/form/widgets/upload' }
+ ];
+ const source = getSourceFile(tree, modulePath);
+ const changes: Change[] = [];
+ for (const item of list) {
+ changes.push(insertImport(source, modulePath, item.symbolName, item.fileName) as InsertChange);
+ changes.push(...addSymbolToNgModuleMetadata(source, modulePath, 'imports', item.symbolName));
+ }
+ applyChanges(tree, modulePath, changes);
+
+ context.logger.info(
+ colors.yellow(
+ ` [@delon/form] Register all widgets in ${name} project, you can reduce package size by removing unnecessary parts`
+ )
+ );
+}
+
+function finished(): Rule {
+ return (_tree: Tree, context: SchematicContext) => {
+ context.addTask(new NodePackageInstallTask());
+
+ context.logger.info(
+ colors.green(
+ ` ✓ Congratulations, Abort more detail please refer to upgrade guide https://github.com/ng-alain/ng-alain/issues/2390`
+ )
+ );
+ };
+}
+
+export function v17Rule(): Rule {
+ return async (tree: Tree, context: SchematicContext) => {
+ logStart(context, `Upgrade @delon/* version number`);
+ UpgradeMainVersions(tree);
+ return chain([autoRegisterFormWidgets(), qr(), finished()]);
+ };
+}
diff --git a/schematics/test.ts b/schematics/test.ts
index a7ec22ddf9..af590d6ef1 100644
--- a/schematics/test.ts
+++ b/schematics/test.ts
@@ -13,7 +13,7 @@ const Jasmine = require('jasmine');
const runner = new Jasmine({ projectBaseDir });
// const files = `schematics/**/*.spec.ts`;
-const files = `schematics/ng-update/upgrade-rules/v16/index.spec.ts`;
+const files = `schematics/ng-update/upgrade-rules/v17/index.spec.ts`;
const tests = glob.sync(files).map(p => relative(projectBaseDir, p));
diff --git a/schematics/utils/ast.ts b/schematics/utils/ast.ts
index d68761bb39..20bb40ff16 100644
--- a/schematics/utils/ast.ts
+++ b/schematics/utils/ast.ts
@@ -1,4 +1,5 @@
import { SchematicsException, Tree } from '@angular-devkit/schematics';
+import { Change, InsertChange } from '@schematics/angular/utility/change';
import * as ts from 'typescript';
/** Reads file given path and returns TypeScript source file. */
@@ -10,3 +11,13 @@ export function getSourceFile(tree: Tree, path: string): ts.SourceFile {
const content = buffer.toString();
return ts.createSourceFile(path, content, ts.ScriptTarget.Latest, true);
}
+
+export function applyChanges(tree: Tree, path: string, changes: Change[]): void {
+ const exportRecorder = tree.beginUpdate(path);
+ for (const change of changes) {
+ if (change instanceof InsertChange) {
+ exportRecorder.insertLeft(change.pos, change.toAdd);
+ }
+ }
+ tree.commitUpdate(exportRecorder);
+}
diff --git a/schematics/utils/versions.ts b/schematics/utils/versions.ts
index bedd2b19fb..81501adbb6 100644
--- a/schematics/utils/versions.ts
+++ b/schematics/utils/versions.ts
@@ -37,6 +37,8 @@ export function UpgradeMainVersions(tree: Tree, version: string = VERSION): void
`ng-alain-plugin-theme@DEP-0.0.0-PLACEHOLDER`,
`source-map-explorer@DEP-0.0.0-PLACEHOLDER`,
`@angular/language-service@DEP-0.0.0-PLACEHOLDER`,
+ `ngx-tinymce@DEP-0.0.0-PLACEHOLDER`,
+ `@ng-util/monaco-editor@DEP-0.0.0-PLACEHOLDER`,
`@delon/testing@${version}`
],
'devDependencies'
diff --git a/scripts/ci/utils.sh b/scripts/ci/utils.sh
index 6bd06eec26..5bffed319d 100644
--- a/scripts/ci/utils.sh
+++ b/scripts/ci/utils.sh
@@ -53,7 +53,8 @@ DEPENDENCIES=$(node -p "
'swagger-typescript-api',
'@github/hotkey',
'ng-alain-sts',
- 'ng-alain-plugin-theme'
+ 'ng-alain-plugin-theme',
+ '@ng-util/monaco-editor'
].map(key => key.replace(/\@/g, '\\\\@').replace(/\//g, '\\\\/').replace(/-/g, '\\\\-') + '|' + (vs[key] || dvs[key])).join('\n\t');
")
VERSION=$(node -p "require('./package.json').version")
diff --git a/scripts/site/generate.ts b/scripts/site/generate.ts
index a389b00fc7..8f005a0299 100755
--- a/scripts/site/generate.ts
+++ b/scripts/site/generate.ts
@@ -153,7 +153,7 @@ function generateModule(config: ModuleConfig): void {
const meta: Meta = {
name: handleExploreStr(item.key, '-'),
i18n,
- order: content[defaultLang].meta.order || -1,
+ order: content[defaultLang].meta.order || 100,
cols: content[defaultLang].meta.cols || 1,
meta: contentMetas
};
@@ -214,7 +214,7 @@ function generateModule(config: ModuleConfig): void {
// #region generate meta file
const metaObj = { types: [], ...includeAttributes(config, {}) };
- metaObj.list = metas;
+ metaObj.list = metas.sort((a, b) => a.order - b.order);
generateDoc(
{ data: JSON.stringify(metaObj) } as MetaTemplateData,
diff --git a/scripts/site/route-paths.txt b/scripts/site/route-paths.txt
index 9b7ebc5aad..cf57abb3e2 100644
--- a/scripts/site/route-paths.txt
+++ b/scripts/site/route-paths.txt
@@ -203,6 +203,8 @@
/form/cascader/zh
/form/checkbox/en
/form/checkbox/zh
+/form/color/en
+/form/color/zh
/form/conditional/en
/form/conditional/zh
/form/custom/en
@@ -219,18 +221,20 @@
/form/i18n/zh
/form/layout/en
/form/layout/zh
-/form/markdown/en
-/form/markdown/zh
/form/mention/en
/form/mention/zh
/form/modal/en
/form/modal/zh
+/form/monaco-editor/en
+/form/monaco-editor/zh
/form/number/en
/form/number/zh
/form/object/en
/form/object/zh
/form/qa/en
/form/qa/zh
+/form/qr-code/en
+/form/qr-code/zh
/form/radio/en
/form/radio/zh
/form/rate/en
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 27a3ff17bd..08151bfcb9 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -34,6 +34,7 @@ import { JsonSchemaModule } from './shared/json-schema/json-schema.module';
import { SharedModule } from './shared/shared.module';
import { STWidgetModule } from './shared/st-widget/st-widget.module';
import { CellWidgetModule } from './shared/cell-widget/module';
+import { NuMonacoEditorModule } from '@ng-util/monaco-editor';
export function StartupServiceFactory(startupService: StartupService): () => Promise {
return () => startupService.load();
@@ -72,6 +73,9 @@ function registerElements(injector: Injector, platformId: {}): void {
CellWidgetModule,
RoutesModule,
ExampleModule,
+ NuMonacoEditorModule.forRoot({
+ defaultOptions: { scrollBeyondLastLine: false }
+ }),
NgxTinymceModule.forRoot({
baseURL: 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.9.2/'
}),
diff --git a/src/app/routes/form-pages/form-pages.module.ts b/src/app/routes/form-pages/form-pages.module.ts
index 468c8f7dc9..35c29d0928 100644
--- a/src/app/routes/form-pages/form-pages.module.ts
+++ b/src/app/routes/form-pages/form-pages.module.ts
@@ -24,13 +24,7 @@ const routes: Routes = [
];
@NgModule({
- imports: [
- SharedModule,
- NuMonacoEditorModule.forRoot({
- defaultOptions: { scrollBeyondLastLine: false }
- }),
- RouterModule.forChild(routes)
- ],
+ imports: [SharedModule, RouterModule.forChild(routes), NuMonacoEditorModule],
declarations: COMPONENTS
})
export class FormPagesModule {}
diff --git a/src/app/routes/form-pages/validator/validator.component.ts b/src/app/routes/form-pages/validator/validator.component.ts
index ca130d0c63..c50cff221a 100644
--- a/src/app/routes/form-pages/validator/validator.component.ts
+++ b/src/app/routes/form-pages/validator/validator.component.ts
@@ -19,7 +19,7 @@ import { NzMessageService } from 'ng-zorro-antd/message';
@Component({
selector: 'demo',
template: \`
-
diff --git a/src/app/shared/json-schema/json-schema.module.ts b/src/app/shared/json-schema/json-schema.module.ts
index e4c106a0a4..43932b3b5f 100644
--- a/src/app/shared/json-schema/json-schema.module.ts
+++ b/src/app/shared/json-schema/json-schema.module.ts
@@ -1,19 +1,43 @@
import { NgModule } from '@angular/core';
-import { DelonFormModule, WidgetRegistry } from '@delon/form';
+import { DelonFormModule } from '@delon/form';
+import { AutoCompleteWidgetModule } from '@delon/form/widgets/autocomplete';
+import { CascaderWidgetModule } from '@delon/form/widgets/cascader';
+import { ColorWidgetModule } from '@delon/form/widgets/color';
+import { MentionWidgetModule } from '@delon/form/widgets/mention';
+import { QrCodeWidgetModule } from '@delon/form/widgets/qr-code';
+import { RateWidgetModule } from '@delon/form/widgets/rate';
+import { SegmentedWidgetModule } from '@delon/form/widgets/segmented';
+import { SliderWidgetModule } from '@delon/form/widgets/slider';
+import { TagWidgetModule } from '@delon/form/widgets/tag';
+import { TimeWidgetModule } from '@delon/form/widgets/time';
+import { TransferWidgetModule } from '@delon/form/widgets/transfer';
+import { TreeSelectWidgetModule } from '@delon/form/widgets/tree-select';
+import { UploadWidgetModule } from '@delon/form/widgets/upload';
+import { MonacoEditorWidgetModule } from '@delon/form/widgets-third/monaco-editor';
+import { TinymceWidgetModule } from '@delon/form/widgets-third/tinymce';
-import { TinymceWidget } from '../../../../packages/form/widgets-third/tinymce/tinymce.widget';
import { SharedModule } from '../shared.module';
-export const SCHEMA_THIRDS_COMPONENTS = [TinymceWidget];
-
@NgModule({
- declarations: SCHEMA_THIRDS_COMPONENTS,
- imports: [SharedModule, DelonFormModule.forRoot()],
- exports: [...SCHEMA_THIRDS_COMPONENTS]
+ imports: [
+ SharedModule,
+ DelonFormModule.forRoot(),
+ AutoCompleteWidgetModule,
+ CascaderWidgetModule,
+ TransferWidgetModule,
+ MentionWidgetModule,
+ RateWidgetModule,
+ SliderWidgetModule,
+ TreeSelectWidgetModule,
+ TagWidgetModule,
+ TimeWidgetModule,
+ UploadWidgetModule,
+ ColorWidgetModule,
+ QrCodeWidgetModule,
+ SegmentedWidgetModule,
+ MonacoEditorWidgetModule,
+ TinymceWidgetModule
+ ]
})
-export class JsonSchemaModule {
- constructor(widgetRegistry: WidgetRegistry) {
- widgetRegistry.register(TinymceWidget.KEY, TinymceWidget);
- }
-}
+export class JsonSchemaModule {}
diff --git a/src/app/shared/shared-zorro.module.ts b/src/app/shared/shared-zorro.module.ts
index 8cfe5bcb19..75e5f12e1a 100644
--- a/src/app/shared/shared-zorro.module.ts
+++ b/src/app/shared/shared-zorro.module.ts
@@ -26,6 +26,7 @@ import { NzMessageModule } from 'ng-zorro-antd/message';
import { NzModalModule } from 'ng-zorro-antd/modal';
import { NzPaginationModule } from 'ng-zorro-antd/pagination';
import { NzPopoverModule } from 'ng-zorro-antd/popover';
+import { NzQRCodeModule } from 'ng-zorro-antd/qr-code';
import { NzRadioModule } from 'ng-zorro-antd/radio';
import { NzResizableModule } from 'ng-zorro-antd/resizable';
import { NzSelectModule } from 'ng-zorro-antd/select';
@@ -77,5 +78,6 @@ export const SHARED_ZORRO_MODULES = [
NzUploadModule,
NzPaginationModule,
NzEmptyModule,
- NzHighlightModule
+ NzHighlightModule,
+ NzQRCodeModule
];
diff --git a/src/site.config.js b/src/site.config.js
index 9c55c2a95d..30c58a8ad1 100644
--- a/src/site.config.js
+++ b/src/site.config.js
@@ -408,6 +408,10 @@ module.exports = {
'zh-CN': '小部件',
'en-US': 'Widgets',
},
+ {
+ 'zh-CN': '非内置小部件',
+ 'en-US': 'Non-built-in widgets',
+ },
{
'zh-CN': '第三方小部件',
'en-US': 'Third Widgets',
@@ -450,6 +454,13 @@ module.exports = {
},
hasSubDir: true,
},
+ {
+ src: ['./packages/form/widgets'],
+ template: {
+ content: './src/templates/content.ts',
+ },
+ hasSubDir: true,
+ },
{
src: ['./packages/form/widgets-third'],
template: {