@libs-ui/components-inputs-add 0.2.355-14 → 0.2.355-15
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 +253 -2
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -1,3 +1,254 @@
|
|
|
1
|
-
# inputs-add
|
|
1
|
+
# @libs-ui/components-inputs-add
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Component cho phép thêm/xóa nhiều input fields động với validation và customization đầy đủ
|
|
4
|
+
|
|
5
|
+
**Version:** 0.2.355-14
|
|
6
|
+
|
|
7
|
+
## Giới thiệu
|
|
8
|
+
|
|
9
|
+
`LibsUiComponentsInputsAddComponent` là một standalone Angular component để quản lý danh sách các input fields động. Component cho phép người dùng thêm/xóa fields, validate từng field riêng biệt, và kiểm tra duplicate values.
|
|
10
|
+
|
|
11
|
+
### Tính năng
|
|
12
|
+
|
|
13
|
+
- ✅ Thêm/xóa input fields động
|
|
14
|
+
- ✅ Validation cho từng field riêng biệt
|
|
15
|
+
- ✅ Kiểm tra duplicate values
|
|
16
|
+
- ✅ Min/Max items configuration
|
|
17
|
+
- ✅ Custom button configuration
|
|
18
|
+
- ✅ OnPush Change Detection
|
|
19
|
+
- ✅ Angular Signals
|
|
20
|
+
- ✅ Two-way binding với items array
|
|
21
|
+
|
|
22
|
+
## Khi nào sử dụng
|
|
23
|
+
|
|
24
|
+
- Cần nhập nhiều giá trị cùng loại (emails, phone numbers, URLs...)
|
|
25
|
+
- Cho phép người dùng thêm/xóa fields động
|
|
26
|
+
- Cần validation cho từng field riêng biệt
|
|
27
|
+
- Quản lý danh sách inputs với min/max items
|
|
28
|
+
- Cần kiểm tra duplicate values giữa các fields
|
|
29
|
+
|
|
30
|
+
## Important Notes
|
|
31
|
+
|
|
32
|
+
⚠️ **fieldNameBind Required**: Phải truyền fieldNameBind để xác định property name trong items array.
|
|
33
|
+
|
|
34
|
+
⚠️ **items Model**: items là model (two-way binding), component tự động cập nhật array khi add/remove.
|
|
35
|
+
|
|
36
|
+
⚠️ **Validation Timing**: Validation chạy sau 250ms debounce khi value change hoặc remove item.
|
|
37
|
+
|
|
38
|
+
⚠️ **ignoreValidEmptyField**: Khi true, chỉ cần ít nhất 1 field có giá trị là valid (không bắt buộc tất cả).
|
|
39
|
+
|
|
40
|
+
## Cài đặt
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# npm
|
|
44
|
+
npm install @libs-ui/components-inputs-add
|
|
45
|
+
|
|
46
|
+
# yarn
|
|
47
|
+
yarn add @libs-ui/components-inputs-add
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Import
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { LibsUiComponentsInputsAddComponent, IInputAdd, IInputAddFunctionControlEvent } from '@libs-ui/components-inputs-add';
|
|
54
|
+
|
|
55
|
+
@Component({
|
|
56
|
+
standalone: true,
|
|
57
|
+
imports: [LibsUiComponentsInputsAddComponent],
|
|
58
|
+
// ...
|
|
59
|
+
})
|
|
60
|
+
export class YourComponent {}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Ví dụ
|
|
64
|
+
|
|
65
|
+
### Basic
|
|
66
|
+
|
|
67
|
+
```html
|
|
68
|
+
<libs_ui-components-inputs-add
|
|
69
|
+
[fieldNameBind]="'email'"
|
|
70
|
+
[(items)]="emailItems"
|
|
71
|
+
[placeholder]="'Nhập email'"
|
|
72
|
+
[labelConfig]="{
|
|
73
|
+
labelLeft: 'Email addresses',
|
|
74
|
+
required: true
|
|
75
|
+
}" />
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
export class ExampleComponent {
|
|
80
|
+
emailItems = signal<Array<IInputAdd>>([{ email: '' }]);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Min/Max Items
|
|
85
|
+
|
|
86
|
+
```html
|
|
87
|
+
<libs_ui-components-inputs-add
|
|
88
|
+
[fieldNameBind]="'phone'"
|
|
89
|
+
[(items)]="phoneItems"
|
|
90
|
+
[minItems]="2"
|
|
91
|
+
[maxItems]="10"
|
|
92
|
+
[placeholder]="'Nhập số điện thoại'" />
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### With Validation & Duplicate Check
|
|
96
|
+
|
|
97
|
+
```html
|
|
98
|
+
<libs_ui-components-inputs-add
|
|
99
|
+
[fieldNameBind]="'url'"
|
|
100
|
+
[(items)]="urlItems"
|
|
101
|
+
[placeholder]="'https://example.com'"
|
|
102
|
+
[validRequired]="{
|
|
103
|
+
isRequired: true,
|
|
104
|
+
message: 'URL is required'
|
|
105
|
+
}"
|
|
106
|
+
[validDuplicate]="{
|
|
107
|
+
message: 'URL already exists'
|
|
108
|
+
}"
|
|
109
|
+
(outValueChange)="onValueChange($event)"
|
|
110
|
+
(outFunctionsControl)="onFunctionsControl($event)" />
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
export class ExampleComponent {
|
|
115
|
+
urlItems = signal<Array<IInputAdd>>([{ url: '' }]);
|
|
116
|
+
functionControls = signal<IInputAddFunctionControlEvent | null>(null);
|
|
117
|
+
|
|
118
|
+
onValueChange(event: IEmitValueChange) {
|
|
119
|
+
console.log('Value changed:', event.value, event.item);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async validateAll() {
|
|
123
|
+
const isValid = await this.functionControls()?.checkIsValid();
|
|
124
|
+
console.log('Is valid:', isValid);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Custom Button & Ignore Empty Field Validation
|
|
130
|
+
|
|
131
|
+
```html
|
|
132
|
+
<libs_ui-components-inputs-add
|
|
133
|
+
[fieldNameBind]="'tag'"
|
|
134
|
+
[(items)]="tagItems"
|
|
135
|
+
[maxItems]="8"
|
|
136
|
+
[ignoreValidEmptyField]="true"
|
|
137
|
+
[addItemButtonConfig]="{
|
|
138
|
+
type: 'button-primary',
|
|
139
|
+
label: 'Add Tag',
|
|
140
|
+
classIconLeft: 'libs-ui-icon-add'
|
|
141
|
+
}"
|
|
142
|
+
[validRequired]="{
|
|
143
|
+
isRequired: true,
|
|
144
|
+
message: 'At least one tag is required'
|
|
145
|
+
}" />
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## API
|
|
149
|
+
|
|
150
|
+
### libs_ui-components-inputs-add
|
|
151
|
+
|
|
152
|
+
#### Inputs
|
|
153
|
+
|
|
154
|
+
| Property | Type | Default | Description |
|
|
155
|
+
| ------------------------- | ---------------------- | ----------- | ----------------------------------------- |
|
|
156
|
+
| `[acceptNegativeValue]` | `boolean` | `false` | Cho phép giá trị âm (với dataType number) |
|
|
157
|
+
| `[addItemButtonConfig]` | `IButton` | `undefined` | Cấu hình button "Add New" |
|
|
158
|
+
| `[autoRemoveEmoji]` | `boolean` | `false` | Tự động loại bỏ emoji khỏi input |
|
|
159
|
+
| `[classInclude]` | `string` | `undefined` | Class CSS cho container chính |
|
|
160
|
+
| `[classIncludeInput]` | `string` | `undefined` | Class CSS cho mỗi input field |
|
|
161
|
+
| `[configItemAddToItems]` | `IInputAdd` | `undefined` | Template config khi add item mới |
|
|
162
|
+
| `[dataType]` | `TYPE_DATA_TYPE_INPUT` | `undefined` | Loại dữ liệu: text, number, email... |
|
|
163
|
+
| `[disable]` | `boolean` | `false` | Disable tất cả inputs |
|
|
164
|
+
| `[fieldNameBind]` | `string` | `required` | Tên property trong items array |
|
|
165
|
+
| `[formInputSpacing]` | `number` | `8` | Khoảng cách giữa các input (px) |
|
|
166
|
+
| `[ignoreAddItem]` | `boolean` | `false` | Ẩn button "Add New" |
|
|
167
|
+
| `[ignoreRemove]` | `boolean` | `false` | Ẩn button remove |
|
|
168
|
+
| `[ignoreValidEmptyField]` | `boolean` | `false` | Chỉ cần ít nhất 1 field có giá trị |
|
|
169
|
+
| `[items]` | `Array<IInputAdd>` | `required` | Array items (model binding) |
|
|
170
|
+
| `[labelConfig]` | `ILabel` | `undefined` | Cấu hình label cho component |
|
|
171
|
+
| `[maxItems]` | `number` | `5` | Số lượng items tối đa |
|
|
172
|
+
| `[maxLength]` | `number` | `undefined` | Độ dài tối đa cho input |
|
|
173
|
+
| `[minItems]` | `number` | `1` | Số lượng items tối thiểu |
|
|
174
|
+
| `[placeholder]` | `string` | `undefined` | Placeholder cho inputs |
|
|
175
|
+
| `[readonly]` | `boolean` | `false` | Readonly tất cả inputs |
|
|
176
|
+
| `[validDuplicate]` | `IMessageTranslate` | `undefined` | Message khi có giá trị duplicate |
|
|
177
|
+
| `[validRequired]` | `IValidRequired` | `undefined` | Validation required |
|
|
178
|
+
|
|
179
|
+
#### Outputs
|
|
180
|
+
|
|
181
|
+
| Property | Type | Description |
|
|
182
|
+
| ----------------------- | ------------------------------- | ------------------------- |
|
|
183
|
+
| `(outAddItem)` | `IInputAdd` | Emit khi thêm item mới |
|
|
184
|
+
| `(outFunctionsControl)` | `IInputAddFunctionControlEvent` | Emit function controls |
|
|
185
|
+
| `(outRemove)` | `IInputAdd` | Emit khi xóa item |
|
|
186
|
+
| `(outValueChange)` | `IEmitValueChange` | Emit khi giá trị thay đổi |
|
|
187
|
+
|
|
188
|
+
#### FunctionsControl Methods
|
|
189
|
+
|
|
190
|
+
| Method | Description |
|
|
191
|
+
| -------------------------- | --------------------------------------------------------- |
|
|
192
|
+
| `checkIsValid()` | Kiểm tra validation tất cả items, trả về Promise<boolean> |
|
|
193
|
+
| `setMessageError(message)` | Set error message cho tất cả items |
|
|
194
|
+
|
|
195
|
+
## Types & Interfaces
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
interface IInputAdd extends Record<string, any> {
|
|
199
|
+
uniqKey?: string;
|
|
200
|
+
disable?: boolean;
|
|
201
|
+
readonly?: boolean;
|
|
202
|
+
ignoreRemove?: boolean;
|
|
203
|
+
placeholder?: string;
|
|
204
|
+
maxValueNumber?: number;
|
|
205
|
+
minValueNumber?: number;
|
|
206
|
+
maxLength?: number;
|
|
207
|
+
functionControl?: IInputValidFunctionControlEvent;
|
|
208
|
+
[key: string]: any;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
interface IInputAddFunctionControlEvent {
|
|
212
|
+
checkIsValid: () => Promise<boolean>;
|
|
213
|
+
setMessageError: (message: string) => Promise<void>;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
interface IEmitValueChange {
|
|
217
|
+
value: string | number;
|
|
218
|
+
item: IInputAdd;
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Công nghệ
|
|
223
|
+
|
|
224
|
+
| Technology | Version | Purpose |
|
|
225
|
+
| --------------- | ------- | ---------------- |
|
|
226
|
+
| Angular | 18+ | Framework |
|
|
227
|
+
| Angular Signals | - | State management |
|
|
228
|
+
| TailwindCSS | 3.x | Styling |
|
|
229
|
+
| OnPush | - | Change Detection |
|
|
230
|
+
|
|
231
|
+
## Demo
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
npx nx serve core-ui
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Truy cập: `http://localhost:4500/inputs/add`
|
|
238
|
+
|
|
239
|
+
## Unit Tests
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
# Chạy tests
|
|
243
|
+
npx nx test components-inputs-add
|
|
244
|
+
|
|
245
|
+
# Coverage
|
|
246
|
+
npx nx test components-inputs-add --coverage
|
|
247
|
+
|
|
248
|
+
# Watch mode
|
|
249
|
+
npx nx test components-inputs-add --watch
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## License
|
|
253
|
+
|
|
254
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libs-ui/components-inputs-add",
|
|
3
|
-
"version": "0.2.355-
|
|
3
|
+
"version": "0.2.355-15",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/common": ">=18.0.0",
|
|
6
6
|
"@angular/core": ">=18.0.0",
|
|
7
|
-
"@libs-ui/components-buttons-button": "0.2.355-
|
|
8
|
-
"@libs-ui/components-inputs-valid": "0.2.355-
|
|
9
|
-
"@libs-ui/components-label": "0.2.355-
|
|
10
|
-
"@libs-ui/components-switch": "0.2.355-
|
|
11
|
-
"@libs-ui/interfaces-types": "0.2.355-
|
|
12
|
-
"@libs-ui/utils": "0.2.355-
|
|
7
|
+
"@libs-ui/components-buttons-button": "0.2.355-15",
|
|
8
|
+
"@libs-ui/components-inputs-valid": "0.2.355-15",
|
|
9
|
+
"@libs-ui/components-label": "0.2.355-15",
|
|
10
|
+
"@libs-ui/components-switch": "0.2.355-15",
|
|
11
|
+
"@libs-ui/interfaces-types": "0.2.355-15",
|
|
12
|
+
"@libs-ui/utils": "0.2.355-15",
|
|
13
13
|
"@ngx-translate/core": "^15.0.0",
|
|
14
|
-
"@libs-ui/components-inputs-input": "0.2.355-
|
|
14
|
+
"@libs-ui/components-inputs-input": "0.2.355-15"
|
|
15
15
|
},
|
|
16
16
|
"sideEffects": false,
|
|
17
17
|
"module": "fesm2022/libs-ui-components-inputs-add.mjs",
|