@ticatec/uniface-element 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +320 -1
- package/README_CN.md +392 -0
- package/dist/accordion/Accordion.svelte +1 -1
- package/dist/action-bar/ActionBar.svelte +7 -1
- package/dist/attachment-files/FileRender.svelte +1 -1
- package/dist/attachment-files/FileUploadBar.svelte +7 -6
- package/dist/attachment-files/FileUploadPanel.svelte +2 -2
- package/dist/base-calendar/DateContext.js +5 -4
- package/dist/base-calendar/YearPickupPanel.svelte +4 -4
- package/dist/card/Card.svelte +1 -1
- package/dist/card/Card.svelte.d.ts +1 -1
- package/dist/cascade-options-select/CascadeOptionSelect.svelte +2 -3
- package/dist/cascade-options-select/CascadeOptionSelect.svelte.d.ts +46 -1
- package/dist/cascade-options-select/CascadePanel.svelte +1 -1
- package/dist/checkbox/CheckBox.svelte +1 -1
- package/dist/color-picker/ColorPicker.svelte +9 -9
- package/dist/color-picker/ColorPicker.svelte.d.ts +0 -2
- package/dist/color-picker/ColorPickerPanel.svelte +11 -15
- package/dist/color-picker/ColorPickerPanel.svelte.d.ts +1 -1
- package/dist/common/CommonPicker.svelte +2 -2
- package/dist/common/CommonPicker.svelte.d.ts +1 -1
- package/dist/common/MouseClickHandler.d.ts +1 -1
- package/dist/common/Popover.svelte +28 -6
- package/dist/common/Popover.svelte.d.ts +9 -3
- package/dist/common/uniface-utils.js +6 -4
- package/dist/common-editor/CommonEditor.svelte +1 -1
- package/dist/common-editor/CommonEditor.svelte.d.ts +1 -1
- package/dist/common-editor/NumberInput.svelte +1 -1
- package/dist/common-editor/NumberInput.svelte.d.ts +1 -1
- package/dist/concise-data-table/ConciseListTable.svelte +7 -2
- package/dist/concise-data-table/ConciseListTable.svelte.d.ts +1 -0
- package/dist/concise-data-table/DataRow.svelte +1 -1
- package/dist/concise-data-table/TableOptions.d.ts +1 -1
- package/dist/data-table/DataTable.svelte +1 -1
- package/dist/data-table/parts/ActionsPanel.svelte +4 -3
- package/dist/data-table/parts/ActionsRow.svelte +3 -3
- package/dist/data-table/parts/ContentPanel.svelte +3 -2
- package/dist/data-table/parts/FixedColumnsPanel.svelte +0 -1
- package/dist/data-table/parts/FixedColumnsPanel.svelte.d.ts +1 -2
- package/dist/data-table/parts/FixedHeaderPanel.svelte +2 -2
- package/dist/data-table/parts/FixedRow.svelte +2 -1
- package/dist/data-table/parts/FixedRow.svelte.d.ts +1 -1
- package/dist/data-table/parts/HrefCell.svelte +23 -2
- package/dist/data-table/parts/PopupMenu.svelte +25 -2
- package/dist/data-table/parts/PopupMenu.svelte.d.ts +8 -1
- package/dist/date-picker/DatePicker.svelte +0 -1
- package/dist/date-picker/DateTimePicker.svelte +3 -3
- package/dist/date-picker/ScrollBar.svelte +4 -7
- package/dist/date-range/DateRangeEditor.svelte +1 -1
- package/dist/dialog/CommonDialog.svelte +8 -5
- package/dist/dialog/CommonDialog.svelte.d.ts +2 -1
- package/dist/dialog/Dialog.svelte +37 -12
- package/dist/dialog/Dialog.svelte.d.ts +4 -3
- package/dist/dialog/DialogBoard.svelte +11 -8
- package/dist/dialog/DialogWrapper.svelte +10 -0
- package/dist/{common-editor/DateInput.svelte.d.ts → dialog/DialogWrapper.svelte.d.ts} +6 -13
- package/dist/dialog/Dialogs.js +1 -1
- package/dist/dialog/ModalResult.d.ts +5 -0
- package/dist/dialog/ModalResult.js +5 -0
- package/dist/drawer/Drawer.svelte +1 -1
- package/dist/form-field/FormField.svelte +2 -1
- package/dist/form-field/FormField.svelte.d.ts +1 -0
- package/dist/form-panel/flex-row-form/FormContainer.svelte +1 -1
- package/dist/form-panel/grid-form/EmptyCell.svelte +8 -7
- package/dist/form-panel/grid-form/EmptyCell.svelte.d.ts +2 -2
- package/dist/form-panel/grid-form/GridField.svelte +1 -1
- package/dist/i18nRes/i18nRes.d.ts +2 -0
- package/dist/i18nRes/i18nRes.js +44 -0
- package/dist/i18nRes/index.d.ts +2 -0
- package/dist/i18nRes/index.js +2 -0
- package/dist/image-files/ImageFilesField.svelte +1 -1
- package/dist/indicator/IndicatorBoard.svelte +1 -1
- package/dist/inline-cell-editor/InvalidEditor.svelte +1 -0
- package/dist/input-options-select/InputOptionsSelect.svelte +6 -6
- package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +1 -1
- package/dist/layout/flex/FlexBlock.svelte +1 -1
- package/dist/lookup-editor/LookupEditor.svelte +1 -1
- package/dist/memo-editor/MemoEditor.svelte +2 -2
- package/dist/message-box/IMessageBox.d.ts +2 -4
- package/dist/message-box/IMessageBox.js +4 -6
- package/dist/message-box/MessageBoxBoard.svelte +1 -3
- package/dist/options-multi-select/OptionsMultiSelect.svelte +1 -1
- package/dist/prompts-text-editor/PromptsTextEditor.svelte +2 -2
- package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +1 -1
- package/dist/property-editor/PropertyEditor.svelte +3 -3
- package/dist/text-editor/PasswordEditor.svelte +1 -1
- package/dist/transfer/Transfer.svelte +17 -12
- package/dist/transfer/Transfer.svelte.d.ts +0 -1
- package/dist/unit-number-editor/UnitNumberEditor.svelte +2 -2
- package/docs/buttons/cn/ActionBar.md +459 -0
- package/docs/buttons/cn/Button.md +228 -0
- package/docs/buttons/cn/IconButton.md +294 -0
- package/docs/buttons/cn/README.md +600 -0
- package/docs/buttons/cn/TextButton.md +163 -0
- package/docs/buttons/en/ActionBar.md +459 -0
- package/docs/buttons/en/Button.md +228 -0
- package/docs/buttons/en/IconButton.md +294 -0
- package/docs/buttons/en/README.md +600 -0
- package/docs/buttons/en/TextButton.md +163 -0
- package/docs/containers/cn/accordion.md +622 -0
- package/docs/containers/cn/box.md +445 -0
- package/docs/containers/cn/card.md +404 -0
- package/docs/containers/cn/page.md +576 -0
- package/docs/containers/cn/tabs.md +686 -0
- package/docs/containers/en/accordion.md +622 -0
- package/docs/containers/en/box.md +445 -0
- package/docs/containers/en/card.md +404 -0
- package/docs/containers/en/page.md +576 -0
- package/docs/containers/en/tabs.md +686 -0
- package/docs/data-display/cn/concise-data-table.md +731 -0
- package/docs/data-display/cn/listbox.md +786 -0
- package/docs/data-display/cn/treeview.md +863 -0
- package/docs/data-display/en/concise-data-table.md +732 -0
- package/docs/data-display/en/listbox.md +786 -0
- package/docs/data-display/en/treeview.md +863 -0
- package/docs/data-table/cn/README.md +596 -0
- package/docs/data-table/en/README.md +596 -0
- package/docs/dialog/cn/README.md +767 -0
- package/docs/dialog/en/README.md +767 -0
- package/docs/form/cn/README.md +847 -0
- package/docs/form/en/README.md +847 -0
- package/docs/form-components/cn/README.md +495 -0
- package/docs/form-components/cn/attachmentfilesfield.md +757 -0
- package/docs/form-components/cn/cascade-options-select.md +374 -0
- package/docs/form-components/cn/checkbox.md +58 -0
- package/docs/form-components/cn/date-picker.md +138 -0
- package/docs/form-components/cn/datetime-picker.md +228 -0
- package/docs/form-components/cn/group-checkbox.md +405 -0
- package/docs/form-components/cn/group-radiobox.md +525 -0
- package/docs/form-components/cn/imagefilesfield.md +651 -0
- package/docs/form-components/cn/input-options-select.md +250 -0
- package/docs/form-components/cn/lookup-editor.md +406 -0
- package/docs/form-components/cn/memoeditor.md +409 -0
- package/docs/form-components/cn/number-editor.md +261 -0
- package/docs/form-components/cn/options-multi-select.md +177 -0
- package/docs/form-components/cn/options-select.md +83 -0
- package/docs/form-components/cn/passwordeditor.md +538 -0
- package/docs/form-components/cn/prompts-text-editor.md +241 -0
- package/docs/form-components/cn/radiobutton.md +84 -0
- package/docs/form-components/cn/switch.md +178 -0
- package/docs/form-components/cn/text-editor.md +142 -0
- package/docs/form-components/cn/time-editor.md +159 -0
- package/docs/form-components/cn/unit-number-editor.md +164 -0
- package/docs/form-components/en/README.md +463 -0
- package/docs/form-components/en/attachmentfilesfield.md +757 -0
- package/docs/form-components/en/cascade-options-select.md +358 -0
- package/docs/form-components/en/checkbox.md +59 -0
- package/docs/form-components/en/date-picker.md +138 -0
- package/docs/form-components/en/datetime-picker.md +228 -0
- package/docs/form-components/en/group-checkbox.md +395 -0
- package/docs/form-components/en/group-radiobox.md +498 -0
- package/docs/form-components/en/imagefilesfield.md +651 -0
- package/docs/form-components/en/input-options-select.md +239 -0
- package/docs/form-components/en/lookup-editor.md +389 -0
- package/docs/form-components/en/memoeditor.md +409 -0
- package/docs/form-components/en/number-editor.md +249 -0
- package/docs/form-components/en/options-multi-select.md +177 -0
- package/docs/form-components/en/options-select.md +83 -0
- package/docs/form-components/en/passwordeditor.md +538 -0
- package/docs/form-components/en/prompts-text-editor.md +241 -0
- package/docs/form-components/en/radiobutton.md +84 -0
- package/docs/form-components/en/switch.md +180 -0
- package/docs/form-components/en/text-editor.md +142 -0
- package/docs/form-components/en/time-editor.md +159 -0
- package/docs/form-components/en/unit-number-editor.md +164 -0
- package/docs/form-layout/cn/criteria-field.md +652 -0
- package/docs/form-layout/cn/flex-form.md +454 -0
- package/docs/form-layout/cn/flex-row-form.md +542 -0
- package/docs/form-layout/cn/form-field.md +923 -0
- package/docs/form-layout/cn/grid-form.md +676 -0
- package/docs/form-layout/en/criteria-field.md +652 -0
- package/docs/form-layout/en/flex-form.md +454 -0
- package/docs/form-layout/en/flex-row-form.md +542 -0
- package/docs/form-layout/en/form-field.md +923 -0
- package/docs/form-layout/en/grid-form.md +676 -0
- package/docs/global/cn/README.md +534 -0
- package/docs/global/en/README.md +534 -0
- package/docs/layout/cn/classiclayout.md +460 -0
- package/docs/layout/cn/headerlayout.md +524 -0
- package/docs/layout/cn/sidebarlayout.md +263 -0
- package/docs/layout/en/classiclayout.md +951 -0
- package/docs/layout/en/headerlayout.md +524 -0
- package/docs/layout/en/sidebarlayout.md +262 -0
- package/docs/misc/cn/README.md +1217 -0
- package/docs/misc/en/README.md +1217 -0
- package/docs/navigation/cn/breadcrumb.md +291 -0
- package/docs/navigation/cn/navigator.md +322 -0
- package/docs/navigation/cn/navigatormenu.md +512 -0
- package/docs/navigation/cn/progressbar.md +199 -0
- package/docs/navigation/cn/progressstepbar.md +299 -0
- package/docs/navigation/en/breadcrumb.md +291 -0
- package/docs/navigation/en/navigator.md +322 -0
- package/docs/navigation/en/navigatormenu.md +512 -0
- package/docs/navigation/en/progressbar.md +199 -0
- package/docs/navigation/en/progressstepbar.md +299 -0
- package/docs/search-filters/cn/daterange.md +1156 -0
- package/docs/search-filters/cn/numberrange.md +688 -0
- package/docs/search-filters/cn/searchbox.md +1582 -0
- package/docs/search-filters/en/daterange.md +1156 -0
- package/docs/search-filters/en/numberrange.md +688 -0
- package/docs/search-filters/en/searchbox.md +1582 -0
- package/package.json +53 -13
- package/dist/common-editor/DateInput.svelte +0 -27
- package/dist/i18n_resources/index.d.ts +0 -3
- package/dist/i18n_resources/index.js +0 -3
- /package/dist/{i18n_resources → i18nRes}/uniface_cn_resource.d.ts +0 -0
- /package/dist/{i18n_resources → i18nRes}/uniface_cn_resource.js +0 -0
- /package/dist/{i18n_resources → i18nRes}/uniface_en_resource.d.ts +0 -0
- /package/dist/{i18n_resources → i18nRes}/uniface_en_resource.js +0 -0
|
@@ -0,0 +1,847 @@
|
|
|
1
|
+
# 表单组件
|
|
2
|
+
|
|
3
|
+
Uniface Element 表单组件为 Svelte 应用程序提供了一套全面的输入控件,用于构建丰富的表单和数据录入界面。这些组件设计有一致的样式、验证支持和灵活的配置选项。
|
|
4
|
+
|
|
5
|
+
> **重要说明**:表单组件通常独立使用,不需要配合标签。当需要标签和错误处理时,可以与 `FormField` 组件配合使用来显示标签和错误信息。对于高级验证,建议集成 [@ticatec/web-bean-validator](https://github.com/ticatec/web-bean-validator) 进行全面的表单验证。
|
|
6
|
+
|
|
7
|
+
## 目录
|
|
8
|
+
|
|
9
|
+
- [FormField 集成](#formfield-集成)
|
|
10
|
+
- [Web Bean Validator 验证](#web-bean-validator-验证)
|
|
11
|
+
- [架构概述](#架构概述)
|
|
12
|
+
- [TextEditor 组件](#texteditor-组件)
|
|
13
|
+
- [NumberEditor 组件](#numbereditor-组件)
|
|
14
|
+
- [TimeEditor 组件](#timeeditor-组件)
|
|
15
|
+
- [UnitNumberEditor 组件](#unitnumbereditor-组件)
|
|
16
|
+
- [CheckBox 组件](#checkbox-组件)
|
|
17
|
+
- [RadioButton 组件](#radiobutton-组件)
|
|
18
|
+
- [OptionsSelect 组件](#optionsselect-组件)
|
|
19
|
+
- [OptionsMultiSelect 组件](#optionsmultiselect-组件)
|
|
20
|
+
- [PromptsTextEditor 组件](#promptstexteditor-组件)
|
|
21
|
+
- [Switch 组件](#switch-组件)
|
|
22
|
+
- [InputOptionsSelect 组件](#inputoptionsselect-组件)
|
|
23
|
+
- [LookupEditor 组件](#lookupeditor-组件)
|
|
24
|
+
- [DatePicker 组件](#datepicker-组件)
|
|
25
|
+
- [DateTimePicker 组件](#datetimepicker-组件)
|
|
26
|
+
- [CascadeOptionsSelect 组件](#cascadeoptionsselect-组件)
|
|
27
|
+
- [通用属性](#通用属性)
|
|
28
|
+
- [显示模式](#显示模式)
|
|
29
|
+
- [样式和主题](#样式和主题)
|
|
30
|
+
- [验证和事件](#验证和事件)
|
|
31
|
+
- [最佳实践](#最佳实践)
|
|
32
|
+
- [无障碍访问](#无障碍访问)
|
|
33
|
+
|
|
34
|
+
## FormField 集成
|
|
35
|
+
|
|
36
|
+
表单组件与 `FormField` 组件完美配合,提供标签、错误信息和一致的表单布局:
|
|
37
|
+
|
|
38
|
+
```svelte
|
|
39
|
+
<script lang="ts">
|
|
40
|
+
import TextEditor, FormField from '@ticatec/uniface-element/TextEditor, FormField';
|
|
41
|
+
|
|
42
|
+
let userEmail = '';
|
|
43
|
+
let emailError = '';
|
|
44
|
+
|
|
45
|
+
const validateEmail = (value: string) => {
|
|
46
|
+
if (!value) {
|
|
47
|
+
emailError = '邮箱是必填项';
|
|
48
|
+
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
|
|
49
|
+
emailError = '请输入有效的邮箱地址';
|
|
50
|
+
} else {
|
|
51
|
+
emailError = '';
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<FormField
|
|
57
|
+
label="邮箱地址"
|
|
58
|
+
error={emailError}
|
|
59
|
+
required={true}
|
|
60
|
+
>
|
|
61
|
+
<TextEditor
|
|
62
|
+
bind:value={userEmail}
|
|
63
|
+
placeholder="输入您的邮箱"
|
|
64
|
+
onChange={validateEmail}
|
|
65
|
+
/>
|
|
66
|
+
</FormField>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Web Bean Validator 验证
|
|
70
|
+
|
|
71
|
+
对于高级表单验证,可以集成 `@ticatec/web-bean-validator` 进行声明式、类型安全的验证:
|
|
72
|
+
|
|
73
|
+
### 安装
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npm install @ticatec/web-bean-validator
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 基本使用
|
|
80
|
+
|
|
81
|
+
```svelte
|
|
82
|
+
<script lang="ts">
|
|
83
|
+
import TextEditor, NumberEditor, FormField from '@ticatec/uniface-element/TextEditor, NumberEditor, FormField';
|
|
84
|
+
import beanValidator from '@ticatec/web-bean-validator';
|
|
85
|
+
import { StringValidator, NumberValidator } from '@ticatec/entity-validator';
|
|
86
|
+
|
|
87
|
+
let formData = {
|
|
88
|
+
name: '',
|
|
89
|
+
email: '',
|
|
90
|
+
age: null
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
let errors = {};
|
|
94
|
+
|
|
95
|
+
// 定义验证规则
|
|
96
|
+
const validationRules = [
|
|
97
|
+
new StringValidator('name', { minLen: 2, required: true }),
|
|
98
|
+
new StringValidator('email', {
|
|
99
|
+
required: true,
|
|
100
|
+
format: {
|
|
101
|
+
regex: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
102
|
+
message: '邮箱格式无效'
|
|
103
|
+
}
|
|
104
|
+
}),
|
|
105
|
+
new NumberValidator('age', { min: 18, max: 120, required: false })
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
const validateForm = () => {
|
|
109
|
+
const result = beanValidator.validate(formData, validationRules);
|
|
110
|
+
|
|
111
|
+
// 将验证结果转换为错误对象
|
|
112
|
+
errors = {};
|
|
113
|
+
if (result.errors) {
|
|
114
|
+
result.errors.forEach(error => {
|
|
115
|
+
errors[error.field] = error.message;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return result.isValid;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const handleSubmit = () => {
|
|
123
|
+
if (validateForm()) {
|
|
124
|
+
console.log('表单验证通过:', formData);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
</script>
|
|
128
|
+
|
|
129
|
+
<form class="validation-form">
|
|
130
|
+
<FormField label="姓名" error={errors.name} required>
|
|
131
|
+
<TextEditor
|
|
132
|
+
bind:value={formData.name}
|
|
133
|
+
placeholder="输入您的姓名"
|
|
134
|
+
on:blur={validateForm}
|
|
135
|
+
/>
|
|
136
|
+
</FormField>
|
|
137
|
+
|
|
138
|
+
<FormField label="邮箱" error={errors.email} required>
|
|
139
|
+
<TextEditor
|
|
140
|
+
bind:value={formData.email}
|
|
141
|
+
placeholder="输入您的邮箱"
|
|
142
|
+
on:blur={validateForm}
|
|
143
|
+
/>
|
|
144
|
+
</FormField>
|
|
145
|
+
|
|
146
|
+
<FormField label="年龄" error={errors.age}>
|
|
147
|
+
<NumberEditor
|
|
148
|
+
bind:value={formData.age}
|
|
149
|
+
placeholder="输入您的年龄"
|
|
150
|
+
min={18}
|
|
151
|
+
max={120}
|
|
152
|
+
precision={0}
|
|
153
|
+
on:blur={validateForm}
|
|
154
|
+
/>
|
|
155
|
+
</FormField>
|
|
156
|
+
|
|
157
|
+
<button type="button" on:click={handleSubmit}>
|
|
158
|
+
提交表单
|
|
159
|
+
</button>
|
|
160
|
+
</form>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### 高级验证示例
|
|
164
|
+
|
|
165
|
+
```svelte
|
|
166
|
+
<script lang="ts">
|
|
167
|
+
import DatePicker, FormField from '@ticatec/uniface-element/DatePicker, FormField';
|
|
168
|
+
import beanValidator from '@ticatec/web-bean-validator';
|
|
169
|
+
import { DateValidator } from '@ticatec/entity-validator';
|
|
170
|
+
|
|
171
|
+
let projectData = {
|
|
172
|
+
startDate: null,
|
|
173
|
+
endDate: null
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
let errors = {};
|
|
177
|
+
|
|
178
|
+
// 自定义验证函数
|
|
179
|
+
const validateDateRange = (value: any, data: any) => {
|
|
180
|
+
if (data.endDate && data.startDate && data.endDate < data.startDate) {
|
|
181
|
+
return "结束日期不能早于开始日期";
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const validationRules = [
|
|
186
|
+
new DateValidator('startDate', {
|
|
187
|
+
required: true,
|
|
188
|
+
minDaysAfter: 0 // 不能是过去的日期
|
|
189
|
+
}),
|
|
190
|
+
new DateValidator('endDate', {
|
|
191
|
+
required: true,
|
|
192
|
+
customCheck: validateDateRange
|
|
193
|
+
})
|
|
194
|
+
];
|
|
195
|
+
|
|
196
|
+
const validateDates = () => {
|
|
197
|
+
const result = beanValidator.validate(projectData, validationRules);
|
|
198
|
+
|
|
199
|
+
errors = {};
|
|
200
|
+
if (result.errors) {
|
|
201
|
+
result.errors.forEach(error => {
|
|
202
|
+
errors[error.field] = error.message;
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
</script>
|
|
207
|
+
|
|
208
|
+
<div class="date-range-form">
|
|
209
|
+
<FormField label="开始日期" error={errors.startDate} required>
|
|
210
|
+
<DatePicker
|
|
211
|
+
bind:value={projectData.startDate}
|
|
212
|
+
onChange={validateDates}
|
|
213
|
+
/>
|
|
214
|
+
</FormField>
|
|
215
|
+
|
|
216
|
+
<FormField label="结束日期" error={errors.endDate} required>
|
|
217
|
+
<DatePicker
|
|
218
|
+
bind:value={projectData.endDate}
|
|
219
|
+
onChange={validateDates}
|
|
220
|
+
/>
|
|
221
|
+
</FormField>
|
|
222
|
+
</div>
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## 架构概述
|
|
226
|
+
|
|
227
|
+
Uniface Element 中的表单组件遵循一致的架构:
|
|
228
|
+
|
|
229
|
+
- **CommonEditor**: 提供一致样式和行为的基础包装器
|
|
230
|
+
- **CommonPicker**: 下拉/选择器组件的基础
|
|
231
|
+
- **DisplayMode**: 支持编辑/查看/显示模式
|
|
232
|
+
- **类型安全**: 完整的 TypeScript 支持和适当的类型定义
|
|
233
|
+
- **事件处理**: 一致的 onChange/onSelected 事件模式
|
|
234
|
+
- **图标集成**: 使用 `@ticatec/uniface-google-material-icons`
|
|
235
|
+
|
|
236
|
+
```mermaid
|
|
237
|
+
graph TD
|
|
238
|
+
A[表单组件] --> B[文本输入]
|
|
239
|
+
A --> C[数字输入]
|
|
240
|
+
A --> D[选择输入]
|
|
241
|
+
A --> E[日期时间输入]
|
|
242
|
+
A --> F[布尔输入]
|
|
243
|
+
|
|
244
|
+
B --> B1[TextEditor]
|
|
245
|
+
B --> B2[PromptsTextEditor]
|
|
246
|
+
|
|
247
|
+
C --> C1[NumberEditor]
|
|
248
|
+
C --> C2[UnitNumberEditor]
|
|
249
|
+
C --> C3[TimeEditor]
|
|
250
|
+
|
|
251
|
+
D --> D1[OptionsSelect]
|
|
252
|
+
D --> D2[OptionsMultiSelect]
|
|
253
|
+
D --> D3[CascadeOptionsSelect]
|
|
254
|
+
D --> D4[InputOptionsSelect]
|
|
255
|
+
|
|
256
|
+
E --> E1[DatePicker]
|
|
257
|
+
E --> E2[DateTimePicker]
|
|
258
|
+
|
|
259
|
+
F --> F1[CheckBox]
|
|
260
|
+
F --> F2[RadioButton]
|
|
261
|
+
F --> F3[Switch]
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## TextEditor 组件
|
|
265
|
+
|
|
266
|
+
一个多功能的文本输入组件,支持前缀、后缀和各种样式选项。
|
|
267
|
+
|
|
268
|
+
### 基本用法
|
|
269
|
+
|
|
270
|
+
```svelte
|
|
271
|
+
<script lang="ts">
|
|
272
|
+
import TextEditor from '@ticatec/uniface-element/TextEditor';
|
|
273
|
+
|
|
274
|
+
let userInput = '';
|
|
275
|
+
|
|
276
|
+
const handleChange = (value: string) => {
|
|
277
|
+
console.log('文本改变:', value);
|
|
278
|
+
};
|
|
279
|
+
</script>
|
|
280
|
+
|
|
281
|
+
<TextEditor
|
|
282
|
+
bind:value={userInput}
|
|
283
|
+
placeholder="在此输入文本"
|
|
284
|
+
onChange={handleChange}
|
|
285
|
+
/>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### 高级功能
|
|
289
|
+
|
|
290
|
+
```svelte
|
|
291
|
+
<script lang="ts">
|
|
292
|
+
import TextEditor from '@ticatec/uniface-element/TextEditor';
|
|
293
|
+
|
|
294
|
+
let email = '';
|
|
295
|
+
let searchTerm = '';
|
|
296
|
+
|
|
297
|
+
const handleEmailChange = (value: string) => {
|
|
298
|
+
// 验证邮箱格式
|
|
299
|
+
const isValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
300
|
+
console.log('邮箱有效:', isValid);
|
|
301
|
+
};
|
|
302
|
+
</script>
|
|
303
|
+
|
|
304
|
+
<!-- 带验证的邮箱输入 -->
|
|
305
|
+
<TextEditor
|
|
306
|
+
bind:value={email}
|
|
307
|
+
placeholder="输入邮箱地址"
|
|
308
|
+
prefix="@"
|
|
309
|
+
variant="outlined"
|
|
310
|
+
onChange={handleEmailChange}
|
|
311
|
+
>
|
|
312
|
+
<i class="icon_google_email" slot="leading-icon"></i>
|
|
313
|
+
</TextEditor>
|
|
314
|
+
|
|
315
|
+
<!-- 带清除按钮的搜索输入 -->
|
|
316
|
+
<TextEditor
|
|
317
|
+
bind:value={searchTerm}
|
|
318
|
+
placeholder="搜索..."
|
|
319
|
+
removable={true}
|
|
320
|
+
compact={true}
|
|
321
|
+
>
|
|
322
|
+
<i class="icon_google_search" slot="leading-icon"></i>
|
|
323
|
+
</TextEditor>
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### TextEditor 属性
|
|
327
|
+
|
|
328
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
329
|
+
|------|------|--------|------|
|
|
330
|
+
| `value` | `string` | `''` | 输入值 |
|
|
331
|
+
| `placeholder` | `string` | `''` | 占位符文本 |
|
|
332
|
+
| `disabled` | `boolean` | `false` | 禁用输入 |
|
|
333
|
+
| `readonly` | `boolean` | `false` | 只读模式 |
|
|
334
|
+
| `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | 视觉样式变体 |
|
|
335
|
+
| `compact` | `boolean` | `false` | 紧凑布局 |
|
|
336
|
+
| `prefix` | `string` | `''` | 文本前缀 |
|
|
337
|
+
| `suffix` | `string` | `''` | 文本后缀 |
|
|
338
|
+
| `removable` | `boolean` | `true` | 显示清除按钮 |
|
|
339
|
+
| `displayMode` | `DisplayMode` | `DisplayMode.Edit` | 显示模式 |
|
|
340
|
+
| `onChange` | `(value: string) => void` | - | 改变事件处理器 |
|
|
341
|
+
| `setFocus` | `() => void` | - | 聚焦方法 |
|
|
342
|
+
|
|
343
|
+
## NumberEditor 组件
|
|
344
|
+
|
|
345
|
+
专门的数字输入,具有精度控制、格式化和验证功能。
|
|
346
|
+
|
|
347
|
+
### 基本用法
|
|
348
|
+
|
|
349
|
+
```svelte
|
|
350
|
+
<script lang="ts">
|
|
351
|
+
import NumberEditor from '@ticatec/uniface-element/NumberEditor';
|
|
352
|
+
|
|
353
|
+
let amount = null;
|
|
354
|
+
let quantity = 1;
|
|
355
|
+
|
|
356
|
+
const handleAmountChange = (value: number | null) => {
|
|
357
|
+
console.log('金额:', value);
|
|
358
|
+
};
|
|
359
|
+
</script>
|
|
360
|
+
|
|
361
|
+
<NumberEditor
|
|
362
|
+
bind:value={amount}
|
|
363
|
+
placeholder="输入金额"
|
|
364
|
+
precision={2}
|
|
365
|
+
allowNegative={false}
|
|
366
|
+
onChange={handleAmountChange}
|
|
367
|
+
/>
|
|
368
|
+
|
|
369
|
+
<NumberEditor
|
|
370
|
+
bind:value={quantity}
|
|
371
|
+
min={1}
|
|
372
|
+
max={100}
|
|
373
|
+
precision={0}
|
|
374
|
+
prefix="数量: "
|
|
375
|
+
/>
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### 货币和格式化
|
|
379
|
+
|
|
380
|
+
```svelte
|
|
381
|
+
<script lang="ts">
|
|
382
|
+
let price = 99.99;
|
|
383
|
+
let percentage = 15.5;
|
|
384
|
+
let weight = 2.5;
|
|
385
|
+
</script>
|
|
386
|
+
|
|
387
|
+
<!-- 货币输入 -->
|
|
388
|
+
<NumberEditor
|
|
389
|
+
bind:value={price}
|
|
390
|
+
prefix="¥"
|
|
391
|
+
precision={2}
|
|
392
|
+
allowNegative={false}
|
|
393
|
+
placeholder="0.00"
|
|
394
|
+
/>
|
|
395
|
+
|
|
396
|
+
<!-- 百分比输入 -->
|
|
397
|
+
<NumberEditor
|
|
398
|
+
bind:value={percentage}
|
|
399
|
+
suffix="%"
|
|
400
|
+
precision={1}
|
|
401
|
+
min={0}
|
|
402
|
+
max={100}
|
|
403
|
+
/>
|
|
404
|
+
|
|
405
|
+
<!-- 重量与单位 -->
|
|
406
|
+
<NumberEditor
|
|
407
|
+
bind:value={weight}
|
|
408
|
+
suffix="kg"
|
|
409
|
+
precision={2}
|
|
410
|
+
allowNegative={false}
|
|
411
|
+
>
|
|
412
|
+
<i class="icon_google_scale" slot="leading-icon"></i>
|
|
413
|
+
</NumberEditor>
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### NumberEditor 属性
|
|
417
|
+
|
|
418
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
419
|
+
|------|------|--------|------|
|
|
420
|
+
| `value` | `number \| null` | `null` | 数字值 |
|
|
421
|
+
| `precision` | `number \| null` | `null` | 小数位数 |
|
|
422
|
+
| `min` | `number \| null` | `null` | 最小值 |
|
|
423
|
+
| `max` | `number \| null` | `null` | 最大值 |
|
|
424
|
+
| `allowNegative` | `boolean` | `false` | 允许负数 |
|
|
425
|
+
| `placeholder` | `string` | `''` | 占位符文本 |
|
|
426
|
+
| `prefix` | `string` | `''` | 文本前缀 |
|
|
427
|
+
| `suffix` | `string` | `''` | 文本后缀 |
|
|
428
|
+
| `removable` | `boolean` | `true` | 显示清除按钮 |
|
|
429
|
+
| `onChange` | `OnChangeHandler<number \| null>` | - | 改变事件处理器 |
|
|
430
|
+
|
|
431
|
+
## CheckBox 组件
|
|
432
|
+
|
|
433
|
+
布尔输入组件,支持不确定状态。
|
|
434
|
+
|
|
435
|
+
### 基本用法
|
|
436
|
+
|
|
437
|
+
```svelte
|
|
438
|
+
<script lang="ts">
|
|
439
|
+
import CheckBox from '@ticatec/uniface-element/CheckBox';
|
|
440
|
+
|
|
441
|
+
let agreedToTerms = false;
|
|
442
|
+
let enableNotifications = true;
|
|
443
|
+
|
|
444
|
+
const handleTermsChange = (checked: boolean) => {
|
|
445
|
+
console.log('同意条款:', checked);
|
|
446
|
+
};
|
|
447
|
+
</script>
|
|
448
|
+
|
|
449
|
+
<CheckBox
|
|
450
|
+
bind:value={agreedToTerms}
|
|
451
|
+
label="我同意条款和条件"
|
|
452
|
+
onChange={handleTermsChange}
|
|
453
|
+
/>
|
|
454
|
+
|
|
455
|
+
<CheckBox
|
|
456
|
+
bind:value={enableNotifications}
|
|
457
|
+
label="启用通知"
|
|
458
|
+
compact={true}
|
|
459
|
+
/>
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### 复选框组
|
|
463
|
+
|
|
464
|
+
```svelte
|
|
465
|
+
<script lang="ts">
|
|
466
|
+
let selectedFeatures = {
|
|
467
|
+
darkMode: false,
|
|
468
|
+
notifications: true,
|
|
469
|
+
autoSave: true,
|
|
470
|
+
analytics: false
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
const features = [
|
|
474
|
+
{ key: 'darkMode', label: '深色模式' },
|
|
475
|
+
{ key: 'notifications', label: '推送通知' },
|
|
476
|
+
{ key: 'autoSave', label: '自动保存' },
|
|
477
|
+
{ key: 'analytics', label: '使用分析' }
|
|
478
|
+
];
|
|
479
|
+
|
|
480
|
+
const handleFeatureChange = (key: string) => (checked: boolean) => {
|
|
481
|
+
selectedFeatures[key] = checked;
|
|
482
|
+
selectedFeatures = { ...selectedFeatures };
|
|
483
|
+
};
|
|
484
|
+
</script>
|
|
485
|
+
|
|
486
|
+
<div class="checkbox-group">
|
|
487
|
+
<h3>应用设置</h3>
|
|
488
|
+
{#each features as feature}
|
|
489
|
+
<CheckBox
|
|
490
|
+
value={selectedFeatures[feature.key]}
|
|
491
|
+
label={feature.label}
|
|
492
|
+
onChange={handleFeatureChange(feature.key)}
|
|
493
|
+
/>
|
|
494
|
+
{/each}
|
|
495
|
+
</div>
|
|
496
|
+
|
|
497
|
+
<style>
|
|
498
|
+
.checkbox-group {
|
|
499
|
+
display: flex;
|
|
500
|
+
flex-direction: column;
|
|
501
|
+
gap: 12px;
|
|
502
|
+
}
|
|
503
|
+
</style>
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### CheckBox 属性
|
|
507
|
+
|
|
508
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
509
|
+
|------|------|--------|------|
|
|
510
|
+
| `value` | `boolean` | `false` | 复选框状态 |
|
|
511
|
+
| `label` | `string \| null` | `null` | 复选框标签 |
|
|
512
|
+
| `indeterminate` | `boolean` | `false` | 不确定状态 |
|
|
513
|
+
| `disabled` | `boolean` | `false` | 禁用复选框 |
|
|
514
|
+
| `readonly` | `boolean` | `false` | 只读模式 |
|
|
515
|
+
| `compact` | `boolean` | `false` | 紧凑布局 |
|
|
516
|
+
| `autoFocus` | `boolean` | `false` | 挂载时自动聚焦 |
|
|
517
|
+
| `onChange` | `OnChangeHandler<boolean>` | - | 改变事件处理器 |
|
|
518
|
+
| `onClick` | `(event: MouseEvent) => void` | - | 点击事件处理器 |
|
|
519
|
+
| `setFocus` | `() => void` | - | 聚焦方法 |
|
|
520
|
+
|
|
521
|
+
## OptionsSelect 组件
|
|
522
|
+
|
|
523
|
+
带有搜索和过滤功能的下拉选择组件。
|
|
524
|
+
|
|
525
|
+
### 基本用法
|
|
526
|
+
|
|
527
|
+
```svelte
|
|
528
|
+
<script lang="ts">
|
|
529
|
+
import OptionsSelect from '@ticatec/uniface-element/OptionsSelect';
|
|
530
|
+
|
|
531
|
+
let selectedCountry = null;
|
|
532
|
+
let selectedCategory = 'electronics';
|
|
533
|
+
|
|
534
|
+
const countries = [
|
|
535
|
+
{ code: 'CN', text: '中国' },
|
|
536
|
+
{ code: 'US', text: '美国' },
|
|
537
|
+
{ code: 'UK', text: '英国' },
|
|
538
|
+
{ code: 'JP', text: '日本' }
|
|
539
|
+
];
|
|
540
|
+
|
|
541
|
+
const categories = [
|
|
542
|
+
{ code: 'electronics', text: '电子产品' },
|
|
543
|
+
{ code: 'clothing', text: '服装' },
|
|
544
|
+
{ code: 'books', text: '图书' },
|
|
545
|
+
{ code: 'home', text: '家居用品' }
|
|
546
|
+
];
|
|
547
|
+
|
|
548
|
+
const handleCountryChange = (value: any) => {
|
|
549
|
+
console.log('选择的国家:', value);
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
const handleCountrySelected = (item: any) => {
|
|
553
|
+
console.log('选择的国家对象:', item);
|
|
554
|
+
};
|
|
555
|
+
</script>
|
|
556
|
+
|
|
557
|
+
<OptionsSelect
|
|
558
|
+
bind:value={selectedCountry}
|
|
559
|
+
options={countries}
|
|
560
|
+
keyField="code"
|
|
561
|
+
textField="text"
|
|
562
|
+
placeholder="选择国家"
|
|
563
|
+
onChange={handleCountryChange}
|
|
564
|
+
onSelected={handleCountrySelected}
|
|
565
|
+
/>
|
|
566
|
+
|
|
567
|
+
<OptionsSelect
|
|
568
|
+
bind:value={selectedCategory}
|
|
569
|
+
options={categories}
|
|
570
|
+
keyField="code"
|
|
571
|
+
textField="text"
|
|
572
|
+
mandatory={true}
|
|
573
|
+
/>
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
### OptionsSelect 属性
|
|
577
|
+
|
|
578
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
579
|
+
|------|------|--------|------|
|
|
580
|
+
| `value` | `any` | `null` | 选择的值 |
|
|
581
|
+
| `options` | `Array<any>` | - | 可用选项 |
|
|
582
|
+
| `keyField` | `string` | `'code'` | 键字段名 |
|
|
583
|
+
| `textField` | `string` | `'text'` | 显示文本字段 |
|
|
584
|
+
| `placeholder` | `string` | `''` | 占位符文本 |
|
|
585
|
+
| `emptyText` | `string` | - | 空值的文本 |
|
|
586
|
+
| `mandatory` | `boolean` | `false` | 必须选择 |
|
|
587
|
+
| `disableOptions` | `string[]` | `[]` | 禁用的选项键 |
|
|
588
|
+
| `hideOptions` | `string[]` | `[]` | 隐藏的选项键 |
|
|
589
|
+
| `itemRender` | `any` | `null` | 自定义项渲染器 |
|
|
590
|
+
| `menu$height` | `number` | `0` | 菜单高度(像素) |
|
|
591
|
+
| `onChange` | `OnChangeHandler<any>` | - | 改变事件处理器 |
|
|
592
|
+
| `onSelected` | `OnSelectedHandler` | - | 选择事件处理器 |
|
|
593
|
+
| `setFocus` | `() => void` | - | 聚焦方法 |
|
|
594
|
+
|
|
595
|
+
## 通用属性
|
|
596
|
+
|
|
597
|
+
大多数表单组件共享这些通用属性:
|
|
598
|
+
|
|
599
|
+
### 样式属性
|
|
600
|
+
|
|
601
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
602
|
+
|------|------|--------|------|
|
|
603
|
+
| `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | 视觉样式变体 |
|
|
604
|
+
| `compact` | `boolean` | `false` | 紧凑布局模式 |
|
|
605
|
+
| `style` | `string` | `''` | 自定义 CSS 样式 |
|
|
606
|
+
| `class` | `string` | `''` | CSS 类名 |
|
|
607
|
+
|
|
608
|
+
### 状态属性
|
|
609
|
+
|
|
610
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
611
|
+
|------|------|--------|------|
|
|
612
|
+
| `disabled` | `boolean` | `false` | 禁用组件 |
|
|
613
|
+
| `readonly` | `boolean` | `false` | 只读模式 |
|
|
614
|
+
| `mandatory` | `boolean` | `false` | 必填字段 |
|
|
615
|
+
|
|
616
|
+
### 行为属性
|
|
617
|
+
|
|
618
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
619
|
+
|------|------|--------|------|
|
|
620
|
+
| `placeholder` | `string` | `''` | 占位符文本 |
|
|
621
|
+
| `displayMode` | `DisplayMode` | `DisplayMode.Edit` | 显示模式 |
|
|
622
|
+
|
|
623
|
+
## 显示模式
|
|
624
|
+
|
|
625
|
+
组件支持不同的显示模式:
|
|
626
|
+
|
|
627
|
+
```typescript
|
|
628
|
+
enum DisplayMode {
|
|
629
|
+
Edit = 'edit', // 完整的编辑功能
|
|
630
|
+
View = 'view', // 只读显示
|
|
631
|
+
Display = 'display' // 最小显示模式
|
|
632
|
+
}
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
### 使用示例
|
|
636
|
+
|
|
637
|
+
```svelte
|
|
638
|
+
<script lang="ts">
|
|
639
|
+
import DisplayMode from '@ticatec/uniface-element/DisplayMode';
|
|
640
|
+
|
|
641
|
+
let currentMode = DisplayMode.Edit;
|
|
642
|
+
let userInput = '示例文本';
|
|
643
|
+
</script>
|
|
644
|
+
|
|
645
|
+
<!-- 编辑模式 - 完全交互 -->
|
|
646
|
+
<TextEditor
|
|
647
|
+
bind:value={userInput}
|
|
648
|
+
displayMode={DisplayMode.Edit}
|
|
649
|
+
placeholder="编辑我"
|
|
650
|
+
/>
|
|
651
|
+
|
|
652
|
+
<!-- 查看模式 - 只读显示 -->
|
|
653
|
+
<TextEditor
|
|
654
|
+
value={userInput}
|
|
655
|
+
displayMode={DisplayMode.View}
|
|
656
|
+
/>
|
|
657
|
+
|
|
658
|
+
<!-- 显示模式 - 最小呈现 -->
|
|
659
|
+
<TextEditor
|
|
660
|
+
value={userInput}
|
|
661
|
+
displayMode={DisplayMode.Display}
|
|
662
|
+
/>
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
## 样式和主题
|
|
666
|
+
|
|
667
|
+
### CSS 自定义属性
|
|
668
|
+
|
|
669
|
+
表单组件使用 CSS 自定义属性进行主题设置:
|
|
670
|
+
|
|
671
|
+
```css
|
|
672
|
+
:root {
|
|
673
|
+
--uniface-primary-color: #007bff;
|
|
674
|
+
--uniface-border-color: #ddd;
|
|
675
|
+
--uniface-background-color: #fff;
|
|
676
|
+
--uniface-text-color: #333;
|
|
677
|
+
--uniface-disabled-color: #999;
|
|
678
|
+
--uniface-focus-color: #0056b3;
|
|
679
|
+
}
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
### 变体样式
|
|
683
|
+
|
|
684
|
+
```svelte
|
|
685
|
+
<!-- 默认样式 -->
|
|
686
|
+
<TextEditor value="默认样式" />
|
|
687
|
+
|
|
688
|
+
<!-- 朴素变体 - 最小边框 -->
|
|
689
|
+
<TextEditor value="朴素样式" variant="plain" />
|
|
690
|
+
|
|
691
|
+
<!-- 轮廓变体 - 突出边框 -->
|
|
692
|
+
<TextEditor value="轮廓样式" variant="outlined" />
|
|
693
|
+
|
|
694
|
+
<!-- 填充变体 - 背景填充 -->
|
|
695
|
+
<TextEditor value="填充样式" variant="filled" />
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
## 事件处理
|
|
699
|
+
|
|
700
|
+
表单组件提供一致的事件处理模式,用于响应用户交互和数据变化。
|
|
701
|
+
|
|
702
|
+
## 最佳实践
|
|
703
|
+
|
|
704
|
+
### 1. 使用 FormField 显示标签和处理错误
|
|
705
|
+
|
|
706
|
+
当需要标签、错误信息或表单结构时,始终使用 `FormField`:
|
|
707
|
+
|
|
708
|
+
```svelte
|
|
709
|
+
<!-- 推荐:使用 FormField -->
|
|
710
|
+
<FormField label="用户名" error={nameError} required>
|
|
711
|
+
<TextEditor bind:value={userName} placeholder="输入姓名" />
|
|
712
|
+
</FormField>
|
|
713
|
+
|
|
714
|
+
<!-- 独立使用:仅在不需要标签/错误时 -->
|
|
715
|
+
<TextEditor bind:value={searchQuery} placeholder="搜索..." />
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
### 2. 在复杂表单中集成 Web Bean Validator
|
|
719
|
+
|
|
720
|
+
对于有多个验证规则的表单,使用 `@ticatec/web-bean-validator`:
|
|
721
|
+
|
|
722
|
+
```svelte
|
|
723
|
+
<script lang="ts">
|
|
724
|
+
import beanValidator from '@ticatec/web-bean-validator';
|
|
725
|
+
import { StringValidator, NumberValidator } from '@ticatec/entity-validator';
|
|
726
|
+
|
|
727
|
+
const rules = [
|
|
728
|
+
new StringValidator('email', { required: true, format: emailRegex }),
|
|
729
|
+
new NumberValidator('age', { min: 18, max: 120 })
|
|
730
|
+
];
|
|
731
|
+
|
|
732
|
+
const validateForm = () => beanValidator.validate(formData, rules);
|
|
733
|
+
</script>
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
### 3. 使用合适的输入类型
|
|
737
|
+
|
|
738
|
+
为您的数据类型选择正确的组件:
|
|
739
|
+
|
|
740
|
+
```svelte
|
|
741
|
+
<!-- 文本数据使用 FormField -->
|
|
742
|
+
<FormField label="姓名" error={errors.name}>
|
|
743
|
+
<TextEditor bind:value={userName} />
|
|
744
|
+
</FormField>
|
|
745
|
+
|
|
746
|
+
<!-- 数字数据 -->
|
|
747
|
+
<FormField label="价格" error={errors.price}>
|
|
748
|
+
<NumberEditor bind:value={price} precision={2} />
|
|
749
|
+
</FormField>
|
|
750
|
+
|
|
751
|
+
<!-- 布尔数据 -->
|
|
752
|
+
<CheckBox bind:value={isEnabled} label="启用通知" />
|
|
753
|
+
|
|
754
|
+
<!-- 选择组件 -->
|
|
755
|
+
<FormField label="分类" error={errors.category}>
|
|
756
|
+
<OptionsSelect bind:value={selectedCategory} options={categories} />
|
|
757
|
+
</FormField>
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
### 4. 提供清晰的标签和占位符
|
|
761
|
+
|
|
762
|
+
```svelte
|
|
763
|
+
<!-- 使用 FormField 而不是手动标签设置 -->
|
|
764
|
+
<FormField label="邮箱地址" required error={emailError}>
|
|
765
|
+
<TextEditor
|
|
766
|
+
bind:value={email}
|
|
767
|
+
placeholder="输入您的邮箱地址"
|
|
768
|
+
variant="outlined"
|
|
769
|
+
/>
|
|
770
|
+
</FormField>
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
### 5. 处理加载状态
|
|
774
|
+
|
|
775
|
+
```svelte
|
|
776
|
+
<script lang="ts">
|
|
777
|
+
let isSubmitting = false;
|
|
778
|
+
|
|
779
|
+
const handleSubmit = async () => {
|
|
780
|
+
isSubmitting = true;
|
|
781
|
+
try {
|
|
782
|
+
await submitForm();
|
|
783
|
+
} finally {
|
|
784
|
+
isSubmitting = false;
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
</script>
|
|
788
|
+
|
|
789
|
+
<TextEditor
|
|
790
|
+
bind:value={formData.field}
|
|
791
|
+
disabled={isSubmitting}
|
|
792
|
+
placeholder={isSubmitting ? "提交中..." : "输入值"}
|
|
793
|
+
/>
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
## 无障碍访问
|
|
797
|
+
|
|
798
|
+
### 当前无障碍功能
|
|
799
|
+
|
|
800
|
+
表单组件包括基本的无障碍功能:
|
|
801
|
+
|
|
802
|
+
- 尽可能使用语义化 HTML 结构
|
|
803
|
+
- 标签关联支持
|
|
804
|
+
- 部分组件的键盘导航
|
|
805
|
+
- 与屏幕阅读器兼容的内容
|
|
806
|
+
|
|
807
|
+
### 无障碍改进
|
|
808
|
+
|
|
809
|
+
为了更好的无障碍性,考虑这些改进:
|
|
810
|
+
|
|
811
|
+
```svelte
|
|
812
|
+
<!-- 适当的标签 -->
|
|
813
|
+
<label for="user-name">全名 *</label>
|
|
814
|
+
<TextEditor
|
|
815
|
+
id="user-name"
|
|
816
|
+
bind:value={userName}
|
|
817
|
+
required
|
|
818
|
+
aria-describedby="name-help"
|
|
819
|
+
/>
|
|
820
|
+
<div id="name-help">输入您的姓名</div>
|
|
821
|
+
|
|
822
|
+
<!-- 错误提示 -->
|
|
823
|
+
<TextEditor
|
|
824
|
+
bind:value={email}
|
|
825
|
+
aria-invalid={emailError ? 'true' : 'false'}
|
|
826
|
+
aria-describedby={emailError ? 'email-error' : undefined}
|
|
827
|
+
/>
|
|
828
|
+
{#if emailError}
|
|
829
|
+
<div id="email-error" role="alert">{emailError}</div>
|
|
830
|
+
{/if}
|
|
831
|
+
|
|
832
|
+
<!-- 字段集分组 -->
|
|
833
|
+
<fieldset>
|
|
834
|
+
<legend>联系偏好</legend>
|
|
835
|
+
<CheckBox value={emailNotifications} label="邮件通知" />
|
|
836
|
+
<CheckBox value={smsNotifications} label="短信通知" />
|
|
837
|
+
</fieldset>
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
## 浏览器支持
|
|
841
|
+
|
|
842
|
+
- 支持 ES2020+ 的现代浏览器
|
|
843
|
+
- 布局需要 CSS Grid 和 Flexbox 支持
|
|
844
|
+
- 增强验证需要表单验证 API
|
|
845
|
+
- 用户交互需要事件处理
|
|
846
|
+
|
|
847
|
+
这份全面指南涵盖了 Uniface Element 库中的主要表单组件,提供了示例、最佳实践和实现细节,用于构建健壮的表单界面。
|