@libs-ui/components-inputs-add 0.2.355-9 → 0.2.356-0

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.
Files changed (2) hide show
  1. package/README.md +319 -2
  2. package/package.json +8 -8
package/README.md CHANGED
@@ -1,3 +1,320 @@
1
- # inputs-add
1
+ # @libs-ui/components-inputs-add
2
2
 
3
- This library was generated with [Nx](https://nx.dev).
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
+ | `[autoAddZeroLessThan10InTypeInt]` | `boolean` | `false` | Tự động thêm số 0 nếu < 10 (kiểu int) |
159
+ | `[autoRemoveEmoji]` | `boolean` | `false` | Tự động loại bỏ emoji khỏi input |
160
+ | `[backgroundNone]` | `boolean` | `false` | Sử dụng background trong suốt |
161
+ | `[borderError]` | `boolean` | `false` | Hiển thị border màu đỏ khi có lỗi |
162
+ | `[classContainerBottomInput]` | `string` | `undefined` | Class CSS cho container dưới input |
163
+ | `[classContainerInput]` | `string` | `undefined` | Class CSS cho container bao quanh input |
164
+ | `[classInclude]` | `string` | `undefined` | Class CSS cho container chính |
165
+ | `[classIncludeInput]` | `string` | `undefined` | Class CSS cho mỗi input field |
166
+ | `[classMessageErrorInclude]` | `string` | `undefined` | Class CSS cho message lỗi |
167
+ | `[configItemAddToItems]` | `IInputAdd` | `undefined` | Template config khi add item mới |
168
+ | `[configUnitLeft]` | `IInputValidUnitConfig` | `{ fieldKey: "id", fieldLabel: "label" }` | Cấu hình hiển thị unit bên trái |
169
+ | `[configUnitRight]` | `IInputValidUnitConfig` | `{ fieldKey: "id", fieldLabel: "label" }` | Cấu hình hiển thị unit bên phải |
170
+ | `[dataType]` | `TYPE_DATA_TYPE_INPUT` | `undefined` | Loại dữ liệu: text, number, email... |
171
+ | `[defaultHeight]` | `number` | `undefined` | Chiều cao mặc định |
172
+ | `[disable]` | `boolean` | `false` | Disable tất cả inputs |
173
+ | `[emitEmptyInDataTypeNumber]` | `boolean` | `false` | Emit giá trị rỗng khi dataType là number |
174
+ | `[fieldNameBind]` | `string` | `required` | Tên property trong items array |
175
+ | `[fixedFloat]` | `number` | `undefined` | Số lượng số lẻ sau dấu phẩy |
176
+ | `[focusTimeOut]` | `number` | `undefined` | Thời gian delay focus |
177
+ | `[formInputSpacing]` | `number` | `8` | Khoảng cách giữa các input (px) |
178
+ | `[functionValid]` | `TYPE_FUNCTION_INPUT_VALID` | `undefined` | Hàm validate tùy chỉnh |
179
+ | `[ignoreAddItem]` | `boolean` | `false` | Ẩn button "Add New" |
180
+ | `[ignoreRemove]` | `boolean` | `false` | Ẩn button remove |
181
+ | `[ignoreShowError]` | `boolean` | `false` | Ẩn hiển thị lỗi |
182
+ | `[ignoreStopPropagationEvent]` | `boolean` | `false` | Không chặn sự kiện lan truyền |
183
+ | `[ignoreUnitRightClassReadOnly]` | `boolean` | `false` | Bỏ class readonly cho unit phải |
184
+ | `[ignoreValidEmptyField]` | `boolean` | `false` | Chỉ cần ít nhất 1 field có giá trị |
185
+ | `[ignoreWidthInput100]` | `boolean` | `false` | Bỏ width 100% cho input |
186
+ | `[isBaselineStyle]` | `boolean` | `false` | Căn chỉnh baseline items |
187
+ | `[items]` | `Array<IInputAdd>` | `required` | Array items (model binding) |
188
+ | `[keepPlaceholderOnly]` | `boolean` | `false` | Chỉ giữ placeholder |
189
+ | `[keySelectedUnitLeft]` | `any` | `undefined` | Key unit trái đang chọn |
190
+ | `[keySelectedUnitRight]` | `any` | `undefined` | Key unit phải đang chọn |
191
+ | `[labelConfig]` | `ILabel` | `undefined` | Cấu hình label cho component |
192
+ | `[leftTemplateItems]` | `ITemplateRightLeftItem` | `undefined` | Template item bên trái |
193
+ | `[maxItems]` | `number` | `5` | Số lượng items tối đa |
194
+ | `[maxLength]` | `number` | `undefined` | Độ dài tối đa cho input |
195
+ | `[maxLengthNumberCount]` | `number` | `undefined` | Max length cho number count |
196
+ | `[maxValueNumber]` | `number` | `undefined` | Giá trị số tối đa |
197
+ | `[minItems]` | `number` | `1` | Số lượng items tối thiểu |
198
+ | `[minValueNumber]` | `number` | `undefined` | Giá trị số tối thiểu |
199
+ | `[noBorder]` | `boolean` | `false` | Không hiển thị border |
200
+ | `[onlyAcceptNegativeValue]` | `boolean` | `false` | Chỉ chấp nhận số âm |
201
+ | `[paddingRightCustomSpecific]` | `number` | `undefined` | Custom padding phải |
202
+ | `[placeholder]` | `string` | `undefined` | Placeholder cho inputs |
203
+ | `[positionMessageErrorStartInput]` | `boolean` | `false` | Hiển thị lỗi bắt đầu từ input |
204
+ | `[readonly]` | `boolean` | `false` | Readonly tất cả inputs |
205
+ | `[resetAutoCompletePassword]` | `boolean` | `false` | Reset autocomplete password |
206
+ | `[resize]` | `'auto' \| 'none'` | `undefined` | Khả năng resize |
207
+ | `[rightTemplateItems]` | `ITemplateRightLeftItem` | `undefined` | Template item bên phải |
208
+ | `[showCount]` | `boolean` | `false` | Hiển thị đếm ký tự |
209
+ | `[tagInput]` | `TYPE_TAG_INPUT` | `undefined` | Tag input (textarea, input...) |
210
+ | `[templateLeftBottomInput]` | `TemplateRef<TYPE_TEMPLATE_REF>` | `undefined` | Template dưới trái input |
211
+ | `[templateLeftOutlet]` | `TemplateRef<TYPE_TEMPLATE_REF>` | `undefined` | Template outlet bên trái |
212
+ | `[templateRightBottomInput]` | `TemplateRef<TYPE_TEMPLATE_REF>` | `undefined` | Template dưới phải input |
213
+ | `[templateRightOutlet]` | `TemplateRef<TYPE_TEMPLATE_REF>` | `undefined` | Template outlet bên phải |
214
+ | `[typeInput]` | `TYPE_INPUT` | `undefined` | Loại input (text, password...) |
215
+ | `[unitsLeft]` | `Array<any>` | `undefined` | Danh sách units bên trái |
216
+ | `[unitsRight]` | `Array<any>` | `undefined` | Danh sách units bên phải |
217
+ | `[useColorModeExist]` | `boolean` | `false` | Sử dụng color mode có sẵn |
218
+ | `[validDuplicate]` | `IMessageTranslate` | `undefined` | Message khi có giá trị duplicate |
219
+ | `[validMaxValue]` | `IMessageTranslate` | `undefined` | Validate giá trị tối đa |
220
+ | `[validMaxLength]` | `IMessageTranslate` | `undefined` | Validate độ dài tối đa |
221
+ | `[validMinLength]` | `IValidLength` | `undefined` | Validate độ dài tối thiểu |
222
+ | `[validMinValue]` | `IMessageTranslate` | `undefined` | Validate giá trị tối thiểu |
223
+ | `[validPattern]` | `Array<IValidPattern>` | `undefined` | Validate theo pattern regex |
224
+ | `[validRequired]` | `IValidRequired` | `undefined` | Validation required |
225
+ | `[valuePatternShowError]` | `boolean` | `false` | Hiển thị lỗi pattern |
226
+ | `[valueUpDownNumber]` | `number` | `undefined` | Bước nhảy tăng giảm số |
227
+
228
+ #### Outputs
229
+
230
+ | Property | Type | Description |
231
+ | ----------------------- | ------------------------------- | -------------------------------- |
232
+ | `(outAddItem)` | `IInputAdd` | Emit khi thêm item mới |
233
+ | `(outClickButtonLabel)` | `IButton` | Emit khi click button trên label |
234
+ | `(outFunctionsControl)` | `IInputAddFunctionControlEvent` | Emit function controls |
235
+ | `(outLabelLeftClick)` | `MouseEvent` | Emit khi click label trái |
236
+ | `(outLabelRightClick)` | `boolean` | Emit khi click label phải |
237
+ | `(outRemove)` | `IInputAdd` | Emit khi xóa item |
238
+ | `(outSwitchEventLabel)` | `ISwitchEvent` | Emit sự kiện switch trên label |
239
+ | `(outValueChange)` | `IEmitValueChange` | Emit khi giá trị thay đổi |
240
+
241
+ #### FunctionsControl Methods
242
+
243
+ | Method | Description |
244
+ | -------------------------- | --------------------------------------------------------- |
245
+ | `checkIsValid()` | Kiểm tra validation tất cả items, trả về Promise<boolean> |
246
+ | `setMessageError(message)` | Set error message cho tất cả items |
247
+
248
+ ## Types & Interfaces
249
+
250
+ ```typescript
251
+ interface IInputAdd extends Record<string, any> {
252
+ uniqKey?: string;
253
+ disable?: boolean;
254
+ readonly?: boolean;
255
+ ignoreRemove?: boolean;
256
+ labelConfig?: ILabel;
257
+ placeholder?: string;
258
+ maxValueNumber?: number;
259
+ minValueNumber?: number;
260
+ maxLength?: number;
261
+
262
+ unitsLeft?: Array<any>;
263
+ configUnitLeft?: IInputValidUnitConfig;
264
+ keySelectedUnitLeft?: any;
265
+
266
+ unitsRight?: Array<any>;
267
+ configUnitRight?: IInputValidUnitConfig;
268
+ keySelectedUnitRight?: any;
269
+
270
+ templateLeftOutlet?: TemplateRef<TYPE_TEMPLATE_REF>;
271
+ templateRightOutlet?: TemplateRef<TYPE_TEMPLATE_REF>;
272
+ functionControl?: IInputValidFunctionControlEvent;
273
+
274
+ [key: string]: any;
275
+ }
276
+
277
+ interface IInputAddFunctionControlEvent {
278
+ checkIsValid: () => Promise<boolean>;
279
+ setMessageError: (message: string) => Promise<void>;
280
+ }
281
+
282
+ interface IEmitValueChange {
283
+ value: string | number;
284
+ item: IInputAdd;
285
+ }
286
+ ```
287
+
288
+ ## Công nghệ
289
+
290
+ | Technology | Version | Purpose |
291
+ | --------------- | ------- | ---------------- |
292
+ | Angular | 18+ | Framework |
293
+ | Angular Signals | - | State management |
294
+ | TailwindCSS | 3.x | Styling |
295
+ | OnPush | - | Change Detection |
296
+
297
+ ## Demo
298
+
299
+ ```bash
300
+ npx nx serve core-ui
301
+ ```
302
+
303
+ Truy cập: `http://localhost:4500/inputs/add`
304
+
305
+ ## Unit Tests
306
+
307
+ ```bash
308
+ # Chạy tests
309
+ npx nx test components-inputs-add
310
+
311
+ # Coverage
312
+ npx nx test components-inputs-add --coverage
313
+
314
+ # Watch mode
315
+ npx nx test components-inputs-add --watch
316
+ ```
317
+
318
+ ## License
319
+
320
+ MIT
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@libs-ui/components-inputs-add",
3
- "version": "0.2.355-9",
3
+ "version": "0.2.356-0",
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-9",
8
- "@libs-ui/components-inputs-valid": "0.2.355-9",
9
- "@libs-ui/components-label": "0.2.355-9",
10
- "@libs-ui/components-switch": "0.2.355-9",
11
- "@libs-ui/interfaces-types": "0.2.355-9",
12
- "@libs-ui/utils": "0.2.355-9",
7
+ "@libs-ui/components-buttons-button": "0.2.356-0",
8
+ "@libs-ui/components-inputs-valid": "0.2.356-0",
9
+ "@libs-ui/components-label": "0.2.356-0",
10
+ "@libs-ui/components-switch": "0.2.356-0",
11
+ "@libs-ui/interfaces-types": "0.2.356-0",
12
+ "@libs-ui/utils": "0.2.356-0",
13
13
  "@ngx-translate/core": "^15.0.0",
14
- "@libs-ui/components-inputs-input": "0.2.355-9"
14
+ "@libs-ui/components-inputs-input": "0.2.356-0"
15
15
  },
16
16
  "sideEffects": false,
17
17
  "module": "fesm2022/libs-ui-components-inputs-add.mjs",