@libs-ui/components-checkbox-group 0.2.356-41 → 0.2.356-43

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 CHANGED
@@ -1,125 +1,437 @@
1
1
  # @libs-ui/components-checkbox-group
2
2
 
3
- > Component quản lý nhóm các checkbox với tính năng validation cấu hình layout linh hoạt cho Angular.
3
+ > Standalone Angular component quản lý nhóm các checkbox với two-way binding, validation bắt buộc chọn, layout linh hoạt API điều khiển từ bên ngoài.
4
4
 
5
5
  ## Giới thiệu
6
6
 
7
- `LibsUiComponentsCheckboxGroupComponent` là một standalone component cho phép hiển thị và quản lý một tập hợp các checkbox. Nó kế thừa đầy đủ sức mạnh của `CheckboxSingleComponent` cho mỗi item trong nhóm và bổ sung các tính năng quản lý tập trung:
7
+ `LibsUiComponentsCheckboxGroupComponent` là component độc lập cho phép hiển thị và quản lý một tập hợp các checkbox trong cùng một nhóm. Nó kế thừa đầy đủ khả năng của `CheckboxSingleComponent` cho mỗi item và bổ sung tính năng quản lý tập trung: theo dõi trạng thái chọn toàn nhóm, validation bắt buộc chọn, set trạng thái nhanh theo danh sách keys, và cấp phát API điều khiển cho component cha thông qua `outFunctionsControl`.
8
8
 
9
- - Quản lý trạng thái chọn hàng loạt thông qua `model`.
10
- - ✅ Hỗ trợ validation bắt buộc chọn (Required selection).
11
- - ✅ Cấu hình giao diện hàng ngang hoặc hàng dọc.
12
- - ✅ Tích hợp nhanh với danh sách keys để set trạng thái chọn/vô hiệu hóa.
13
- - ✅ Hỗ trợ nội dung bổ sung (subText/subTemplate) cho mỗi item.
9
+ ## Tính năng
10
+
11
+ - ✅ Two-way binding danh sách items qua `model()` tự động đồng bộ khi trạng thái checkbox thay đổi
12
+ - ✅ Set trạng thái checked/disabled hàng loạt bằng danh sách keys (`keysChecked`, `keysDisable`)
13
+ - ✅ Layout dọc (mặc định) hoặc ngang (`horizontal`) với tùy chỉnh CSS linh hoạt
14
+ - ✅ Validation bắt buộc chọn tích hợp (`validRequired`) với thông báo lỗi i18n
15
+ - ✅ API điều khiển từ bên ngoài: `checkIsValid()`, `reset()`, `resetError()`
16
+ - ✅ Hỗ trợ nội dung bổ sung cho từng item: `subText`, `subTemplate`
17
+ - ✅ Hiển thị nhãn tổng quát (`labelConfig`) tích hợp component Label
18
+ - ✅ Hỗ trợ viền bao quanh (`modeBorder`) và tùy chỉnh class CSS đầy đủ
19
+
20
+ ## Khi nào sử dụng
21
+
22
+ - Quản lý danh sách lựa chọn nhiều giá trị (multi-select) trong form
23
+ - Cần ràng buộc người dùng phải chọn ít nhất một giá trị trước khi submit
24
+ - Cần hiển thị các checkbox theo hàng ngang để tiết kiệm diện tích màn hình
25
+ - Cần điều khiển trạng thái toàn nhóm từ bên ngoài (reset, validate) thông qua API
26
+ - Cần set sẵn trạng thái checked hoặc disabled cho một số items dựa vào dữ liệu từ API
14
27
 
15
28
  ## Cài đặt
16
29
 
17
30
  ```bash
18
- # npm
19
31
  npm install @libs-ui/components-checkbox-group
32
+ ```
33
+
34
+ ## Import
35
+
36
+ ```typescript
37
+ import {
38
+ LibsUiComponentsCheckboxGroupComponent,
39
+ ICheckboxGroupItem,
40
+ ICheckboxGroupValidRequired,
41
+ ICheckboxGroupFunctionControlEvent,
42
+ ICheckboxItem,
43
+ } from '@libs-ui/components-checkbox-group';
44
+ ```
45
+
46
+ ## Ví dụ sử dụng
47
+
48
+ ### 1. Cơ bản — danh sách dọc với nhãn
49
+
50
+ ```typescript
51
+ import { Component, signal } from '@angular/core';
52
+ import {
53
+ LibsUiComponentsCheckboxGroupComponent,
54
+ ICheckboxGroupItem,
55
+ } from '@libs-ui/components-checkbox-group';
56
+ import { ICheckboxEvent } from '@libs-ui/components-checkbox-single';
57
+
58
+ @Component({
59
+ selector: 'app-skills-form',
60
+ standalone: true,
61
+ imports: [LibsUiComponentsCheckboxGroupComponent],
62
+ template: `
63
+ <libs_ui-components-checkbox-group
64
+ [(groups)]="skillOptions"
65
+ [labelConfig]="{ labelLeft: 'Kỹ năng', required: true }"
66
+ (outChange)="handlerSkillChange($event)"
67
+ />
68
+ `,
69
+ })
70
+ export class SkillsFormComponent {
71
+ skillOptions = signal<ICheckboxGroupItem[]>([
72
+ { item: { key: 'angular', label: 'Angular' } },
73
+ { item: { key: 'react', label: 'React', checked: true } },
74
+ { item: { key: 'vue', label: 'Vue.js' } },
75
+ { item: { key: 'nodejs', label: 'Node.js' } },
76
+ ]);
77
+
78
+ handlerSkillChange(event: ICheckboxEvent): void {
79
+ event.stopPropagation();
80
+ console.log('Checked items:', event.allCheckboxChecked);
81
+ }
82
+ }
83
+ ```
84
+
85
+ ### 2. Layout ngang — chọn thứ trong tuần
86
+
87
+ ```typescript
88
+ import { Component, signal } from '@angular/core';
89
+ import {
90
+ LibsUiComponentsCheckboxGroupComponent,
91
+ ICheckboxGroupItem,
92
+ } from '@libs-ui/components-checkbox-group';
93
+
94
+ @Component({
95
+ selector: 'app-schedule-form',
96
+ standalone: true,
97
+ imports: [LibsUiComponentsCheckboxGroupComponent],
98
+ template: `
99
+ <libs_ui-components-checkbox-group
100
+ [(groups)]="weekDays"
101
+ [horizontal]="true"
102
+ [labelConfig]="{ labelLeft: 'Lịch làm việc' }"
103
+ [classItemWhenModeHorizontal]="'mr-[32px]'"
104
+ />
105
+ `,
106
+ })
107
+ export class ScheduleFormComponent {
108
+ weekDays = signal<ICheckboxGroupItem[]>([
109
+ { item: { key: 'mon', label: 'Thứ 2' } },
110
+ { item: { key: 'tue', label: 'Thứ 3', checked: true } },
111
+ { item: { key: 'wed', label: 'Thứ 4', checked: true } },
112
+ { item: { key: 'thu', label: 'Thứ 5' } },
113
+ { item: { key: 'fri', label: 'Thứ 6', checked: true } },
114
+ ]);
115
+ }
116
+ ```
117
+
118
+ ### 3. Validation bắt buộc chọn
119
+
120
+ ```typescript
121
+ import { Component, signal } from '@angular/core';
122
+ import {
123
+ LibsUiComponentsCheckboxGroupComponent,
124
+ ICheckboxGroupItem,
125
+ } from '@libs-ui/components-checkbox-group';
126
+
127
+ @Component({
128
+ selector: 'app-required-form',
129
+ standalone: true,
130
+ imports: [LibsUiComponentsCheckboxGroupComponent],
131
+ template: `
132
+ <libs_ui-components-checkbox-group
133
+ [(groups)]="categories"
134
+ [labelConfig]="{ labelLeft: 'Danh mục quan tâm', required: true }"
135
+ [validRequired]="{
136
+ message: 'Vui lòng chọn ít nhất một danh mục',
137
+ hasBorderErrorCheckbox: true
138
+ }"
139
+ [showValidateBottom]="true"
140
+ />
141
+ `,
142
+ })
143
+ export class RequiredFormComponent {
144
+ categories = signal<ICheckboxGroupItem[]>([
145
+ { item: { key: 'tech', label: 'Công nghệ' } },
146
+ { item: { key: 'finance', label: 'Tài chính' } },
147
+ { item: { key: 'health', label: 'Sức khỏe' } },
148
+ ]);
149
+ }
150
+ ```
151
+
152
+ ### 4. Điều khiển từ bên ngoài qua API
153
+
154
+ ```typescript
155
+ import { Component, signal } from '@angular/core';
156
+ import {
157
+ LibsUiComponentsCheckboxGroupComponent,
158
+ ICheckboxGroupItem,
159
+ ICheckboxGroupFunctionControlEvent,
160
+ } from '@libs-ui/components-checkbox-group';
161
+
162
+ @Component({
163
+ selector: 'app-form-with-api',
164
+ standalone: true,
165
+ imports: [LibsUiComponentsCheckboxGroupComponent],
166
+ template: `
167
+ <div class="flex gap-2 mb-4">
168
+ <button (click)="handlerReset()">Reset</button>
169
+ <button (click)="handlerValidate()">Validate</button>
170
+ </div>
171
+
172
+ <libs_ui-components-checkbox-group
173
+ [(groups)]="items"
174
+ [validRequired]="{ message: 'Bạn chưa chọn mục nào' }"
175
+ [showValidateBottom]="true"
176
+ (outFunctionsControl)="handlerFunctionsControl($event)"
177
+ />
178
+ `,
179
+ })
180
+ export class FormWithApiComponent {
181
+ items = signal<ICheckboxGroupItem[]>([
182
+ { item: { key: 'item1', label: 'Mục 1' } },
183
+ { item: { key: 'item2', label: 'Mục 2' } },
184
+ { item: { key: 'item3', label: 'Mục 3' } },
185
+ ]);
20
186
 
21
- # yarn
22
- yarn add @libs-ui/components-checkbox-group
187
+ private checkboxControl: ICheckboxGroupFunctionControlEvent | null = null;
188
+
189
+ handlerFunctionsControl(event: ICheckboxGroupFunctionControlEvent): void {
190
+ event.stopPropagation();
191
+ this.checkboxControl = event;
192
+ }
193
+
194
+ handlerReset(): void {
195
+ this.checkboxControl?.reset();
196
+ }
197
+
198
+ handlerValidate(): void {
199
+ this.checkboxControl?.checkIsValid();
200
+ }
201
+ }
23
202
  ```
24
203
 
25
- ## Sử dụng
204
+ ### 5. Set checked/disabled theo keys từ API
26
205
 
27
- ### Import Component
206
+ ```typescript
207
+ import { Component, signal } from '@angular/core';
208
+ import {
209
+ LibsUiComponentsCheckboxGroupComponent,
210
+ ICheckboxGroupItem,
211
+ } from '@libs-ui/components-checkbox-group';
212
+
213
+ @Component({
214
+ selector: 'app-keys-control',
215
+ standalone: true,
216
+ imports: [LibsUiComponentsCheckboxGroupComponent],
217
+ template: `
218
+ <libs_ui-components-checkbox-group
219
+ [(groups)]="permissions"
220
+ [fieldKey]="'id'"
221
+ [keysChecked]="checkedKeys()"
222
+ [keysDisable]="disabledKeys()"
223
+ [labelConfig]="{ labelLeft: 'Quyền truy cập' }"
224
+ />
225
+ `,
226
+ })
227
+ export class KeysControlComponent {
228
+ permissions = signal<ICheckboxGroupItem[]>([
229
+ { item: { id: 'read', label: 'Xem' } },
230
+ { item: { id: 'write', label: 'Chỉnh sửa' } },
231
+ { item: { id: 'delete', label: 'Xóa' } },
232
+ { item: { id: 'admin', label: 'Quản trị' } },
233
+ ]);
234
+
235
+ // Keys sẽ được check sẵn khi component khởi tạo hoặc khi giá trị thay đổi
236
+ checkedKeys = signal<string[]>(['read', 'write']);
237
+
238
+ // Keys sẽ bị vô hiệu hóa
239
+ disabledKeys = signal<string[]>(['admin']);
240
+ }
241
+ ```
242
+
243
+ ### 6. Item với nội dung bổ sung (subText / subTemplate)
28
244
 
29
245
  ```typescript
30
246
  import { Component, signal } from '@angular/core';
31
- import { LibsUiComponentsCheckboxGroupComponent, ICheckboxGroupItem } from '@libs-ui/components-checkbox-group';
247
+ import {
248
+ LibsUiComponentsCheckboxGroupComponent,
249
+ ICheckboxGroupItem,
250
+ } from '@libs-ui/components-checkbox-group';
32
251
 
33
252
  @Component({
34
- selector: 'app-example',
253
+ selector: 'app-subtext-example',
35
254
  standalone: true,
36
255
  imports: [LibsUiComponentsCheckboxGroupComponent],
37
256
  template: `
38
257
  <libs_ui-components-checkbox-group
39
- [(groups)]="options"
40
- [labelConfig]="{ label: 'Chọn sở thích' }"></libs_ui-components-checkbox-group>
258
+ [(groups)]="planOptions"
259
+ [labelConfig]="{ labelLeft: 'Chọn gói dịch vụ' }"
260
+ />
41
261
  `,
42
262
  })
43
- export class ExampleComponent {
44
- options = signal<ICheckboxGroupItem[]>([{ item: { key: 'music', label: 'Âm nhạc' } }, { item: { key: 'sport', label: 'Thể thao' } }, { item: { key: 'reading', label: 'Đọc sách' } }]);
263
+ export class SubtextExampleComponent {
264
+ planOptions = signal<ICheckboxGroupItem[]>([
265
+ {
266
+ item: { key: 'basic', label: 'Gói Cơ bản' },
267
+ subText: 'Bao gồm 5GB lưu trữ và hỗ trợ email.',
268
+ classIncludeSubText: 'text-gray-500 pl-[24px] mt-[4px]',
269
+ },
270
+ {
271
+ item: { key: 'pro', label: 'Gói Pro', checked: true },
272
+ subText: 'Bao gồm 50GB lưu trữ, hỗ trợ 24/7 và API access.',
273
+ classIncludeSubText: 'text-gray-500 pl-[24px] mt-[4px]',
274
+ },
275
+ ]);
45
276
  }
46
277
  ```
47
278
 
48
- ## API Reference
49
-
50
- ### Inputs
51
-
52
- | Tên | Kiểu | Mặc định | tả |
53
- | ------------------------------ | ----------------------------- | ------------- | -------------------------------------------------------------- |
54
- | `classGroupWhenModeHorizontal` | `string` | `'flex'` | Class CSS cho wrapper khi chế độ chiều ngang. |
55
- | `classInclude` | `string` | `undefined` | Class CSS bổ sung cho container chính. |
56
- | `classItemWhenModeHorizontal` | `string` | `'mr-[24px]'` | Class CSS cho mỗi item khi chế độ chiều ngang. |
57
- | `classLabelInclude` | `string` | `undefined` | Class CSS cho nhãn tổng quát của nhóm. |
58
- | `clickExactly` | `boolean` | `true` | Nếu `true`, chỉ click vào checkbox/label mới đổi trạng thái. |
59
- | `disable` | `boolean` | `false` | hiệu hóa tương tác cho toàn bộ nhóm. |
60
- | `fieldKey` | `string` | `'key'` | Tên thuộc tính dùng làm khóa định danh cho item dữ liệu. |
61
- | `groups` | `model<ICheckboxGroupItem[]>` | _required_ | Danh sách các item trong nhóm (hỗ trợ two-way binding). |
62
- | `horizontal` | `boolean` | `false` | Nếu `true`, hiển thị các item theo hàng ngang. |
63
- | `keysChecked` | `string[]` | `undefined` | Danh sách keys của các item cần được chọn sẵn. |
64
- | `keysDisable` | `string[]` | `undefined` | Danh sách keys của các item cần được hiệu hóa. |
65
- | `labelConfig` | `ILabel` | `undefined` | Cấu hình cho component Label hiển thị trên cùng của nhóm. |
66
- | `modeBorder` | `boolean` | `false` | Hiển thị viền bao quanh component. |
67
- | `showValidateBottom` | `boolean` | `false` | Hiển thị thông báo lỗi validation ở dưới cùng. |
68
- | `validRequired` | `ICheckboxGroupValidRequired` | `undefined` | Cấu hình validation bắt buộc người dùng chọn ít nhất một item. |
69
-
70
- ### Outputs
71
-
72
- | Tên | Kiểu | tả |
73
- | --------------------- | ------------------------------------ | ---------------------------------------------------------------------------- |
74
- | `outChange` | `ICheckboxEvent` | Phát ra khi bất kỳ checkbox nào trong nhóm thay đổi trạng thái. |
75
- | `outFunctionsControl` | `ICheckboxGroupFunctionControlEvent` | Cung cấp các hàm điều khiển (API) như `checkIsValid`, `reset`, `resetError`. |
76
-
77
- ## Interfaces & Types
279
+ ## @Input()
280
+
281
+ | Input | Type | Default | Mô tả | Ví dụ |
282
+ |---|---|---|---|---|
283
+ | `[(groups)]` | `ICheckboxGroupItem[]` | _bắt buộc_ | Danh sách items trong nhóm, hỗ trợ two-way binding để đồng bộ trạng thái checked | `[(groups)]="skillOptions"` |
284
+ | `[classGroupWhenModeHorizontal]` | `string` | `'flex'` | Class CSS cho wrapper nhóm khi ở chế độ nằm ngang | `[classGroupWhenModeHorizontal]="'flex flex-wrap'"` |
285
+ | `[classInclude]` | `string` | `undefined` | Class CSS bổ sung cho container checkbox của mỗi item | `[classInclude]="'border rounded'"` |
286
+ | `[classItemWhenModeHorizontal]` | `string` | `'mr-[24px]'` | Class CSS cho mỗi item khi ở chế độ nằm ngang | `[classItemWhenModeHorizontal]="'mr-[32px]'"` |
287
+ | `[classLabelInclude]` | `string` | `undefined` | Class CSS bổ sung cho nhãn của mỗi checkbox | `[classLabelInclude]="'libs-ui-font-h5m'"` |
288
+ | `[clickExactly]` | `boolean` | `true` | Nếu `true`, chỉ click vào ô checkbox/nhãn mới đổi trạng thái; nếu `false`, click vào vùng bao quanh cũng trigger | `[clickExactly]="false"` |
289
+ | `[disable]` | `boolean` | `false` | hiệu hóa tương tác cho toàn bộ nhóm checkbox | `[disable]="isFormLocked()"` |
290
+ | `[fieldKey]` | `string` | `'key'` | Tên trường dùng làm khóa định danh trong object item (dùng khi item data có field tên khác `key`) | `[fieldKey]="'id'"` |
291
+ | `[horizontal]` | `boolean` | `false` | Nếu `true`, hiển thị các item theo hàng ngang thay hàng dọc | `[horizontal]="true"` |
292
+ | `[keysChecked]` | `string[]` | `undefined` | Danh sách giá trị của `fieldKey` cần được set trạng thái checked khi khởi tạo hoặc khi thay đổi | `[keysChecked]="selectedIds()"` |
293
+ | `[keysDisable]` | `string[]` | `undefined` | Danh sách giá trị của `fieldKey` cần được hiệu hóa | `[keysDisable]="lockedIds()"` |
294
+ | `[labelConfig]` | `ILabel` | `undefined` | Cấu hình cho component Label hiển thị phía trên nhóm (nhãn, required, mô tả, nút...) | `[labelConfig]="{ labelLeft: 'Kỹ năng', required: true }"` |
295
+ | `[modeBorder]` | `boolean` | `undefined` | Hiển thị viền bao quanh từng checkbox item | `[modeBorder]="true"` |
296
+ | `[showValidateBottom]` | `boolean` | `undefined` | Nếu `true`, hiển thị thông báo lỗi validation ở phía dưới nhóm; nếu `false` (mặc định), hiển thị ở phía trên | `[showValidateBottom]="true"` |
297
+ | `[validRequired]` | `ICheckboxGroupValidRequired` | `undefined` | Cấu hình validation bắt buộc chọn ít nhất một item. Khi set, component sẽ tự validate khi checkbox thay đổi | `[validRequired]="{ message: 'Vui lòng chọn ít nhất một mục' }"` |
298
+
299
+ ## @Output()
300
+
301
+ | Output | Type | Mô tả | Handler TS | Binding HTML |
302
+ |---|---|---|---|---|
303
+ | `(outChange)` | `ICheckboxEvent` | Phát ra khi bất kỳ checkbox nào trong nhóm thay đổi trạng thái. `event.allCheckboxChecked` chứa danh sách tất cả items đang được chọn | `handlerChange(event: ICheckboxEvent): void { event.stopPropagation(); const selected = event.allCheckboxChecked; }` | `(outChange)="handlerChange($event)"` |
304
+ | `(outFunctionsControl)` | `ICheckboxGroupFunctionControlEvent` | Phát ra object chứa các hàm điều khiển component. Được emit một lần trong `ngOnInit`. Lưu lại để gọi `checkIsValid()`, `reset()`, `resetError()` từ bên ngoài | `handlerFunctionsControl(event: ICheckboxGroupFunctionControlEvent): void { event.stopPropagation(); this.checkboxControl = event; }` | `(outFunctionsControl)="handlerFunctionsControl($event)"` |
305
+
306
+ ## Types & Interfaces
307
+
308
+ ```typescript
309
+ import {
310
+ ICheckboxGroupItem,
311
+ ICheckboxGroupValidRequired,
312
+ ICheckboxGroupFunctionControlEvent,
313
+ ICheckboxItem,
314
+ } from '@libs-ui/components-checkbox-group';
315
+ ```
78
316
 
79
317
  ### ICheckboxGroupItem
80
318
 
319
+ Cấu hình cho mỗi phần tử trong nhóm checkbox.
320
+
81
321
  ```typescript
82
322
  interface ICheckboxGroupItem {
83
- item: ICheckboxItem; // Cấu hình checkbox (xem CheckboxSingle)
84
- subText?: string; // Văn bản bổ sung
85
- subTemplate?: TemplateRef; // Template tùy chỉnh bổ sung
86
- disableByKeys?: boolean; // Trạng thái disable tự động theo keysDisable
323
+ /** Cấu hình chi tiết của checkbox item */
324
+ item: ICheckboxItem;
325
+ /** Văn bản bổ sung hiển thị bên dưới item khi item đang được chọn */
326
+ subText?: string;
327
+ /** Class CSS bổ sung cho phần subText */
328
+ classIncludeSubText?: string;
329
+ /** Template tùy chỉnh hiển thị khi item được chọn */
330
+ subTemplate?: TemplateRef<any>;
331
+ /** Trạng thái vô hiệu hóa tự động khi key nằm trong keysDisable (tự set bởi component) */
332
+ disableByKeys?: boolean;
333
+ }
334
+ ```
335
+
336
+ ### ICheckboxItem
337
+
338
+ Cấu hình chi tiết cho một checkbox đơn lẻ bên trong nhóm.
339
+
340
+ ```typescript
341
+ interface ICheckboxItem {
342
+ /** Khóa định danh duy nhất (dùng với fieldKey='key' mặc định) */
343
+ key?: string;
344
+ /** Trạng thái chọn của checkbox */
345
+ checked?: boolean;
346
+ /** Nhãn văn bản hiển thị cạnh checkbox */
347
+ label?: string;
348
+ /** Class CSS bổ sung cho nhãn */
349
+ classLabelInclude?: string;
350
+ /** Trạng thái vô hiệu hóa của checkbox */
351
+ disable?: boolean;
352
+ /** Vô hiệu hóa tương tác click trên nhãn nhưng vẫn cho click ô checkbox */
353
+ disableLabel?: boolean;
354
+ /** Class CSS bổ sung cho wrapper của item */
355
+ classIncludeWrapper?: string;
356
+ /** Class CSS bổ sung cho ô checkbox */
357
+ classInclude?: string;
358
+ /** Nếu true, chỉ click vào checkbox/label mới trigger (override giá trị clickExactly của group) */
359
+ clickExactly?: boolean;
360
+ /** Cấu hình popover khi di chuột vào nhãn */
361
+ popover?: IPopover;
362
+ /** Loại nội dung popover ('text' | 'component') */
363
+ typeLabelPopover?: TYPE_POPOVER_TYPE;
364
+ /** Ẩn popover khi di chuột vào nhãn */
365
+ ignoreShowPopoverLabel?: boolean;
366
+ /** Cấu hình Avatar hiển thị cạnh checkbox */
367
+ avatarConfig?: IAvatarConfig;
368
+ /** URL hình ảnh hiển thị cạnh checkbox */
369
+ linkImage?: string;
370
+ /** URL hình ảnh dự phòng khi load lỗi */
371
+ linkImageError?: string;
372
+ /** Class CSS bổ sung cho phần hình ảnh */
373
+ classImageInclude?: string;
374
+ /** Cấu hình bullet (chấm tròn màu) */
375
+ bullet?: ICheckboxBullet;
376
+ /** Mô tả chi tiết hiển thị dưới nhãn */
377
+ description?: ICheckboxItemDescription;
378
+ /** Callback xử lý sự kiện từ popover */
379
+ outEventPopover?: (event: TYPE_POPOVER_EVENT) => void;
380
+ /** Các thuộc tính mở rộng — dùng khi fieldKey trỏ đến field khác 'key' */
381
+ [key: string]: any;
382
+ }
383
+ ```
384
+
385
+ ### ICheckboxGroupValidRequired
386
+
387
+ Cấu hình cho tính năng validation bắt buộc chọn.
388
+
389
+ ```typescript
390
+ interface ICheckboxGroupValidRequired {
391
+ /** Thông báo lỗi khi không có item nào được chọn. Hỗ trợ i18n key. */
392
+ message?: string;
393
+ /** Nếu true, hiển thị viền đỏ trên các ô checkbox khi có lỗi validation */
394
+ hasBorderErrorCheckbox?: boolean;
395
+ /** Tham số nội suy cho thông báo lỗi i18n (dùng với TranslateModule) */
396
+ interpolateParams?: any;
87
397
  }
88
398
  ```
89
399
 
90
400
  ### ICheckboxGroupFunctionControlEvent
91
401
 
402
+ API điều khiển component từ bên ngoài, nhận được qua `(outFunctionsControl)`.
403
+
92
404
  ```typescript
93
405
  interface ICheckboxGroupFunctionControlEvent {
94
- checkIsValid: () => Promise<boolean>; // Kiểm tra tính hợp lệ (validation)
95
- resetError: () => Promise<void>; // Xóa hiển thị lỗi
96
- reset: () => Promise<void>; // Reset toàn bộ về trạng thái chưa chọn
406
+ /** Kích hoạt validation, trả về true nếu ít nhất một item được chọn */
407
+ checkIsValid: () => Promise<boolean>;
408
+ /** Xóa trạng thái hiển thị lỗi validation */
409
+ resetError: () => Promise<void>;
410
+ /** Reset toàn bộ nhóm về trạng thái chưa chọn và xóa lỗi */
411
+ reset: () => Promise<void>;
97
412
  }
98
413
  ```
99
414
 
100
- ## Công nghệ sử dụng
415
+ ## Lưu ý quan trọng
101
416
 
102
- - **Angular 18+** - Standalone Components
103
- - **Angular Signals & Model** - Modern reactive state management
104
- - **NG-Zorro Style Integration**
417
+ ⚠️ **`groups` model bắt buộc**: Input `[(groups)]` là `model.required()` — component sẽ báo lỗi runtime nếu không truyền vào. Luôn khởi tạo với mảng hợp lệ (có thể rỗng `[]`).
105
418
 
106
- ## Demo
419
+ ⚠️ **`subText` và `subTemplate` chỉ hiển thị khi item được chọn**: Nội dung bổ sung (`subText`, `subTemplate`) chỉ render khi `group.item.checked === true`. Đây là behavior có chủ đích để hiển thị thông tin chi tiết khi người dùng chọn một option.
107
420
 
108
- Demo sẵn trong ứng dụng `core-ui`:
421
+ ⚠️ **`outFunctionsControl` emit một lần duy nhất trong `ngOnInit`**: Lưu giá trị nhận được từ output này vào biến class để sử dụng sau. Không cần subscribe lại.
109
422
 
110
- ```bash
111
- npx nx serve core-ui
112
- ```
423
+ ⚠️ **`keysChecked` và `keysDisable` phản ứng reactively**: Khi thay đổi giá trị của `keysChecked()` hoặc `keysDisable()`, component tự động cập nhật trạng thái checked/disabled của các items tương ứng. Sử dụng signal cho hai input này để tận dụng tính năng này.
113
424
 
114
- **File demo:** `apps/core-ui/src/app/components/checkbox-group/checkbox-group.component.ts`
425
+ ⚠️ **`fieldKey` phải khớp với tên trường trong item**: Khi dùng `fieldKey` khác `'key'` (ví dụ `'id'`), object trong `ICheckboxItem` phải có trường đó (ví dụ `item.id`).`ICheckboxItem` có `[key: string]: any`, bạn có thể thêm bất kỳ trường nào.
115
426
 
116
- ### Tính năng Demo
427
+ ⚠️ **`disable` cấp group override `disable` cấp item**: Khi `[disable]="true"` trên group, toàn bộ nhóm bị khóa kể cả khi item có `disable: false`. `keysDisable` hoạt động độc lập và không bị override bởi `disable` của group.
428
+
429
+ ## Demo
117
430
 
118
- - 🎮 **Basic Group**: Sử dụng cơ bản với danh sách dọc.
119
- - ↔️ **Horizontal Layout**: Hiển thị items theo hàng ngang.
120
- - ⚠️ **Validation**: Demo tính năng bắt buộc chọn với thông báo lỗi.
121
- - 🛠️ **External Control**: Điều khiển nhóm checkbox bằng API (Reset, Validate).
431
+ ```bash
432
+ npx nx serve core-ui
433
+ ```
122
434
 
123
- ## License
435
+ Truy cập: `http://localhost:4500/components/checkbox/group`
124
436
 
125
- MIT
437
+ File demo: `apps/core-ui/src/app/components/checkbox/group/group.component.ts`
@@ -1,6 +1,6 @@
1
1
  import { NgTemplateOutlet } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { signal, model, input, output, effect, untracked, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { signal, model, input, output, effect, untracked, Component, ChangeDetectionStrategy } from '@angular/core';
4
4
  import { LibsUiComponentsCheckboxSingleComponent } from '@libs-ui/components-checkbox-single';
5
5
  import { LibsUiComponentsLabelComponent } from '@libs-ui/components-label';
6
6
  import { ERROR_MESSAGE_EMPTY_VALID } from '@libs-ui/utils';
@@ -1 +1 @@
1
- {"version":3,"file":"libs-ui-components-checkbox-group.mjs","sources":["../../../../../../libs-ui/components/checkbox/group/src/checkbox-group.component.ts","../../../../../../libs-ui/components/checkbox/group/src/checkbox-group.component.html","../../../../../../libs-ui/components/checkbox/group/src/libs-ui-components-checkbox-group.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, effect, input, model, OnInit, output, signal, untracked } from '@angular/core';\nimport { ICheckboxEvent, LibsUiComponentsCheckboxSingleComponent } from '@libs-ui/components-checkbox-single';\nimport { ILabel, LibsUiComponentsLabelComponent } from '@libs-ui/components-label';\nimport { TYPE_POPOVER_EVENT } from '@libs-ui/components-popover';\nimport { ERROR_MESSAGE_EMPTY_VALID } from '@libs-ui/utils';\nimport { TranslateModule } from '@ngx-translate/core';\nimport { ICheckboxGroupFunctionControlEvent } from './interfaces/function-control.interface';\nimport { ICheckboxGroupItem, ICheckboxGroupValidRequired, ICheckboxItem } from './interfaces/group.interface';\n\n/**\n * Checkbox Group Component - Một tập hợp các checkbox đơn lẻ trong một nhóm.\n *\n * @description\n * Hỗ trợ quản lý danh sách các checkbox, xử lý trạng thái chọn hàng loạt,\n * cấu hình layout (ngang/dọc), và tích hợp validation bắt buộc chọn.\n *\n * @example\n * ```html\n * <libs_ui-components-checkbox-group\n * [(groups)]=\"options\"\n * [labelConfig]=\"{ label: 'Chọn kỹ năng' }\"\n * (outChange)=\"onSelectionChange($event)\"\n * />\n * ```\n *\n * @publicApi\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'libs_ui-components-checkbox-group',\n templateUrl: './checkbox-group.component.html',\n styleUrl: './checkbox-group.component.scss',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [TranslateModule, NgTemplateOutlet, LibsUiComponentsLabelComponent, LibsUiComponentsCheckboxSingleComponent],\n})\nexport class LibsUiComponentsCheckboxGroupComponent implements OnInit {\n // #region PROPERTY\n protected readonly ERROR_MESSAGE_EMPTY_VALID = ERROR_MESSAGE_EMPTY_VALID;\n /** Signal điều khiển trạng thái hiển thị lỗi validation */\n protected error = signal<boolean>(false);\n\n // #region INPUT\n /**\n * Danh sách các item trong nhóm checkbox.\n * Model hỗ trợ two-way binding để cập nhật trạng thái checked của các item.\n */\n readonly groups = model.required<Array<ICheckboxGroupItem>>();\n /** Tên trường đóng vai trò là khóa định danh trong item dữ liệu (mặc định: 'key') */\n readonly fieldKey = input<string, string>('key', { transform: (value) => value || 'key' });\n /** Danh sách các keys cần được set trạng thái checked khi khởi tạo hoặc thay đổi */\n readonly keysChecked = input<Array<string>>();\n /** Danh sách các keys cần được set trạng thái disable */\n readonly keysDisable = input<Array<string>>();\n /** Trạng thái vô hiệu hóa toàn bộ nhóm checkbox */\n readonly disable = input<boolean | undefined, boolean | undefined>(false, { transform: (value) => value ?? false });\n /** Nếu true, chỉ click vào checkbox/label mới đổi trạng thái. Nếu false, click vào vùng bao quanh item sẽ trigger */\n readonly clickExactly = input<boolean | undefined, boolean | undefined>(true, { transform: (value) => value ?? true });\n /** Hiển thị các checkbox theo hàng ngang (mặc định: dọc) */\n readonly horizontal = input<boolean | undefined, boolean | undefined>(false, { transform: (value) => value ?? false });\n /** Cấu hình nhãn (Label) tổng quát cho toàn bộ nhóm */\n readonly labelConfig = input<ILabel>();\n /** Cấu hình validation bắt buộc người dùng phải chọn ít nhất một item */\n readonly validRequired = input<ICheckboxGroupValidRequired>();\n /** Class CSS bổ sung cho container chính của nhóm */\n readonly classInclude = input<string>();\n /** Class CSS bổ sung cho nhãn của nhóm */\n readonly classLabelInclude = input<string>();\n /** Hiển thị thông báo lỗi validation ở phía dưới nhóm */\n readonly showValidateBottom = input<boolean>();\n /** Class CSS cho item khi hiển thị ở chế độ nằm ngang */\n readonly classItemWhenModeHorizontal = input<string>('mr-[24px]');\n /** Class CSS cho wrapper nhóm khi hiển thị ở chế độ nằm ngang */\n readonly classGroupWhenModeHorizontal = input<string>('flex');\n /** Hiển thị viền bao quanh toàn bộ nhóm component */\n readonly modeBorder = input<boolean>();\n\n // #region OUTPUT\n /** Phát ra khi bất kỳ checkbox nào trong nhóm thay đổi trạng thái */\n readonly outChange = output<ICheckboxEvent>();\n /** Phát ra object chứa các hàm điều khiển (API) của component lên component cha */\n readonly outFunctionsControl = output<ICheckboxGroupFunctionControlEvent>();\n\n constructor() {\n effect(() => {\n if (!Array.isArray(this.keysChecked()) || !this.fieldKey()) {\n return;\n }\n untracked(() => {\n this.groups.update((data) => {\n return data.map((group) => {\n group.item.checked = this.keysChecked()?.some((key) => key === group.item[this.fieldKey()]);\n\n return group;\n });\n });\n });\n });\n\n effect(() => {\n if (!Array.isArray(this.keysDisable()) || !this.fieldKey()) {\n return;\n }\n untracked(() => {\n this.groups.update((data) => {\n return data.map((group) => {\n group.disableByKeys = false;\n if (group.item && this.keysDisable()?.includes(group.item[this.fieldKey()])) {\n group.disableByKeys = true;\n }\n return group;\n });\n });\n });\n });\n }\n\n /* FUNCTIONS */\n ngOnInit() {\n this.outFunctionsControl.emit(this.FunctionsControl);\n }\n\n public get FunctionsControl(): ICheckboxGroupFunctionControlEvent {\n return {\n checkIsValid: this.checkValid.bind(this),\n resetError: this.resetError.bind(this),\n reset: async () => {\n this.groups.update((data) => {\n return data.map((group) => {\n group.item.checked = false;\n return group;\n });\n });\n this.resetError();\n },\n };\n }\n\n // #region FUNCTIONS\n protected handlerChange(event: ICheckboxEvent, item: ICheckboxItem) {\n if (this.disable()) {\n return;\n }\n item.checked = event.checked;\n event.allCheckboxChecked = this.groups()\n .filter((group) => group.item.checked)\n .map((group) => ({ key: group.item[this.fieldKey()], item: group.item }));\n this.outChange.emit(event);\n this.checkValid();\n }\n\n private async checkValid() {\n this.error.set(false);\n if (!this.validRequired()) {\n return true;\n }\n this.error.set(!this.groups().some((group) => group.item.checked));\n\n return !this.error();\n }\n\n private async resetError() {\n this.error.set(false);\n }\n\n protected handlerEventPopover(event: TYPE_POPOVER_EVENT, item: ICheckboxItem) {\n item.outEventPopover?.(event);\n }\n}\n","<div class=\"flex flex-col w-full\">\n @if (labelConfig(); as labelConfig) {\n <libs_ui-components-label\n [classInclude]=\"labelConfig.classInclude\"\n [labelLeft]=\"labelConfig.labelLeft\"\n [labelLeftClass]=\"labelConfig.labelLeftClass\"\n [required]=\"labelConfig.required\"\n [description]=\"labelConfig.description\"\n [labelRight]=\"labelConfig.labelRight\"\n [labelRightClass]=\"labelConfig.labelRightClass\"\n [onlyShowCount]=\"labelConfig.onlyShowCount\"\n [buttonsLeft]=\"labelConfig.buttonsLeft\"\n [disableButtonsLeft]=\"labelConfig.disableButtonsLeft || disable()\"\n [hasToggle]=\"labelConfig.hasToggle\"\n [toggleActive]=\"labelConfig.toggleActive\"\n [toggleDisable]=\"labelConfig.toggleDisable || disable()\"\n [popover]=\"labelConfig.popover\"\n [iconPopoverClass]=\"labelConfig.iconPopoverClass\"\n [onlyShowCount]=\"labelConfig.onlyShowCount\"\n [limitLength]=\"labelConfig.limitLength\"\n [buttonsDescription]=\"labelConfig.buttonsDescription\"\n [disableButtonsDescription]=\"labelConfig.disableButtonsDescription || disable()\"\n [buttonsDescriptionContainerClass]=\"labelConfig.buttonsDescriptionContainerClass\"\n [count]=\"labelConfig.count\" />\n }\n @if (!showValidateBottom()) {\n <ng-container *ngTemplateOutlet=\"templateValidate\"></ng-container>\n }\n <div class=\"libs-ui-checkbox-group {{ horizontal() ? classGroupWhenModeHorizontal() : '' }}\">\n @for (group of groups(); track group) {\n <div [class]=\"horizontal() ? classItemWhenModeHorizontal() : ''\">\n <div class=\"py-[4px] {{ group.item.classIncludeWrapper || '' }}\">\n <libs_ui-components-checkbox-single\n [label]=\"group.item.label || ' '\"\n [checked]=\"group.item.checked || false\"\n [key]=\"group.item[fieldKey()]\"\n [disable]=\"group.disableByKeys || disable() || group.item.disable || false\"\n [disableLabel]=\"group.item.disableLabel || false\"\n [classLabelInclude]=\"classLabelInclude() || group.item.classLabelInclude || ''\"\n [classInclude]=\"classInclude() || group.item.classInclude || ''\"\n [popover]=\"group.item.popover\"\n [avatarConfig]=\"group.item.avatarConfig\"\n [description]=\"group.item.description\"\n [typeLabelPopover]=\"group.item.typeLabelPopover || 'text'\"\n [ignoreShowPopoverLabel]=\"group.item.ignoreShowPopoverLabel || false\"\n [clickExactly]=\"clickExactly()\"\n [modeBorder]=\"modeBorder()\"\n [showBorderError]=\"error() && validRequired()?.hasBorderErrorCheckbox\"\n (outChange)=\"handlerChange($event, group.item)\"\n (outEventPopover)=\"handlerEventPopover($event, group.item)\" />\n </div>\n @if (group.item.checked) {\n @if (group.subText) {\n <div\n class=\"libs-ui-checkbox-group-sub-text libs-ui-font-h7r {{ group.classIncludeSubText || '' }}\"\n [innerHtml]=\"group.subText\"></div>\n }\n <ng-container *ngTemplateOutlet=\"group?.subTemplate || null; context: { item: group.item }\"></ng-container>\n }\n </div>\n }\n </div>\n @if (showValidateBottom()) {\n <ng-container *ngTemplateOutlet=\"templateValidate\"></ng-container>\n }\n</div>\n\n<ng-template #templateValidate>\n @if (error()) {\n <div\n class=\"flex items-center\"\n [class.mb-[8px]]=\"!showValidateBottom()\"\n [class.mt-[8px]]=\"showValidateBottom()\">\n @let constHtmlMessage = validRequired()?.message || ERROR_MESSAGE_EMPTY_VALID;\n <span\n class=\"libs-ui-text-error libs-ui-font-h7r\"\n [innerHtml]=\"constHtmlMessage | translate: validRequired()?.interpolateParams\"></span>\n </div>\n }\n</ng-template>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"libs-ui-components-checkbox-group.mjs","sources":["../../../../../../libs-ui/components/checkbox/group/src/checkbox-group.component.ts","../../../../../../libs-ui/components/checkbox/group/src/checkbox-group.component.html","../../../../../../libs-ui/components/checkbox/group/src/libs-ui-components-checkbox-group.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, effect, input, model, OnInit, output, signal, untracked } from '@angular/core';\nimport { ICheckboxEvent, LibsUiComponentsCheckboxSingleComponent } from '@libs-ui/components-checkbox-single';\nimport { ILabel, LibsUiComponentsLabelComponent } from '@libs-ui/components-label';\nimport { TYPE_POPOVER_EVENT } from '@libs-ui/components-popover';\nimport { ERROR_MESSAGE_EMPTY_VALID } from '@libs-ui/utils';\nimport { TranslateModule } from '@ngx-translate/core';\nimport { ICheckboxGroupFunctionControlEvent } from './interfaces/function-control.interface';\nimport { ICheckboxGroupItem, ICheckboxGroupValidRequired, ICheckboxItem } from './interfaces/group.interface';\n\n/**\n * Checkbox Group Component - Một tập hợp các checkbox đơn lẻ trong một nhóm.\n *\n * @description\n * Hỗ trợ quản lý danh sách các checkbox, xử lý trạng thái chọn hàng loạt,\n * cấu hình layout (ngang/dọc), và tích hợp validation bắt buộc chọn.\n *\n * @example\n * ```html\n * <libs_ui-components-checkbox-group\n * [(groups)]=\"options\"\n * [labelConfig]=\"{ label: 'Chọn kỹ năng' }\"\n * (outChange)=\"onSelectionChange($event)\"\n * />\n * ```\n *\n * @publicApi\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'libs_ui-components-checkbox-group',\n templateUrl: './checkbox-group.component.html',\n styleUrl: './checkbox-group.component.scss',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [TranslateModule, NgTemplateOutlet, LibsUiComponentsLabelComponent, LibsUiComponentsCheckboxSingleComponent],\n})\nexport class LibsUiComponentsCheckboxGroupComponent implements OnInit {\n // #region PROPERTY\n protected readonly ERROR_MESSAGE_EMPTY_VALID = ERROR_MESSAGE_EMPTY_VALID;\n /** Signal điều khiển trạng thái hiển thị lỗi validation */\n protected error = signal<boolean>(false);\n\n // #region INPUT\n /**\n * Danh sách các item trong nhóm checkbox.\n * Model hỗ trợ two-way binding để cập nhật trạng thái checked của các item.\n */\n readonly groups = model.required<Array<ICheckboxGroupItem>>();\n /** Tên trường đóng vai trò là khóa định danh trong item dữ liệu (mặc định: 'key') */\n readonly fieldKey = input<string, string>('key', { transform: (value) => value || 'key' });\n /** Danh sách các keys cần được set trạng thái checked khi khởi tạo hoặc thay đổi */\n readonly keysChecked = input<Array<string>>();\n /** Danh sách các keys cần được set trạng thái disable */\n readonly keysDisable = input<Array<string>>();\n /** Trạng thái vô hiệu hóa toàn bộ nhóm checkbox */\n readonly disable = input<boolean | undefined, boolean | undefined>(false, { transform: (value) => value ?? false });\n /** Nếu true, chỉ click vào checkbox/label mới đổi trạng thái. Nếu false, click vào vùng bao quanh item sẽ trigger */\n readonly clickExactly = input<boolean | undefined, boolean | undefined>(true, { transform: (value) => value ?? true });\n /** Hiển thị các checkbox theo hàng ngang (mặc định: dọc) */\n readonly horizontal = input<boolean | undefined, boolean | undefined>(false, { transform: (value) => value ?? false });\n /** Cấu hình nhãn (Label) tổng quát cho toàn bộ nhóm */\n readonly labelConfig = input<ILabel>();\n /** Cấu hình validation bắt buộc người dùng phải chọn ít nhất một item */\n readonly validRequired = input<ICheckboxGroupValidRequired>();\n /** Class CSS bổ sung cho container chính của nhóm */\n readonly classInclude = input<string>();\n /** Class CSS bổ sung cho nhãn của nhóm */\n readonly classLabelInclude = input<string>();\n /** Hiển thị thông báo lỗi validation ở phía dưới nhóm */\n readonly showValidateBottom = input<boolean>();\n /** Class CSS cho item khi hiển thị ở chế độ nằm ngang */\n readonly classItemWhenModeHorizontal = input<string>('mr-[24px]');\n /** Class CSS cho wrapper nhóm khi hiển thị ở chế độ nằm ngang */\n readonly classGroupWhenModeHorizontal = input<string>('flex');\n /** Hiển thị viền bao quanh toàn bộ nhóm component */\n readonly modeBorder = input<boolean>();\n\n // #region OUTPUT\n /** Phát ra khi bất kỳ checkbox nào trong nhóm thay đổi trạng thái */\n readonly outChange = output<ICheckboxEvent>();\n /** Phát ra object chứa các hàm điều khiển (API) của component lên component cha */\n readonly outFunctionsControl = output<ICheckboxGroupFunctionControlEvent>();\n\n constructor() {\n effect(() => {\n if (!Array.isArray(this.keysChecked()) || !this.fieldKey()) {\n return;\n }\n untracked(() => {\n this.groups.update((data) => {\n return data.map((group) => {\n group.item.checked = this.keysChecked()?.some((key) => key === group.item[this.fieldKey()]);\n\n return group;\n });\n });\n });\n });\n\n effect(() => {\n if (!Array.isArray(this.keysDisable()) || !this.fieldKey()) {\n return;\n }\n untracked(() => {\n this.groups.update((data) => {\n return data.map((group) => {\n group.disableByKeys = false;\n if (group.item && this.keysDisable()?.includes(group.item[this.fieldKey()])) {\n group.disableByKeys = true;\n }\n return group;\n });\n });\n });\n });\n }\n\n /* FUNCTIONS */\n ngOnInit() {\n this.outFunctionsControl.emit(this.FunctionsControl);\n }\n\n public get FunctionsControl(): ICheckboxGroupFunctionControlEvent {\n return {\n checkIsValid: this.checkValid.bind(this),\n resetError: this.resetError.bind(this),\n reset: async () => {\n this.groups.update((data) => {\n return data.map((group) => {\n group.item.checked = false;\n return group;\n });\n });\n this.resetError();\n },\n };\n }\n\n // #region FUNCTIONS\n protected handlerChange(event: ICheckboxEvent, item: ICheckboxItem) {\n if (this.disable()) {\n return;\n }\n item.checked = event.checked;\n event.allCheckboxChecked = this.groups()\n .filter((group) => group.item.checked)\n .map((group) => ({ key: group.item[this.fieldKey()], item: group.item }));\n this.outChange.emit(event);\n this.checkValid();\n }\n\n private async checkValid() {\n this.error.set(false);\n if (!this.validRequired()) {\n return true;\n }\n this.error.set(!this.groups().some((group) => group.item.checked));\n\n return !this.error();\n }\n\n private async resetError() {\n this.error.set(false);\n }\n\n protected handlerEventPopover(event: TYPE_POPOVER_EVENT, item: ICheckboxItem) {\n item.outEventPopover?.(event);\n }\n}\n","<div class=\"flex flex-col w-full\">\n @if (labelConfig(); as labelConfig) {\n <libs_ui-components-label\n [classInclude]=\"labelConfig.classInclude\"\n [labelLeft]=\"labelConfig.labelLeft\"\n [labelLeftClass]=\"labelConfig.labelLeftClass\"\n [required]=\"labelConfig.required\"\n [description]=\"labelConfig.description\"\n [labelRight]=\"labelConfig.labelRight\"\n [labelRightClass]=\"labelConfig.labelRightClass\"\n [onlyShowCount]=\"labelConfig.onlyShowCount\"\n [buttonsLeft]=\"labelConfig.buttonsLeft\"\n [disableButtonsLeft]=\"labelConfig.disableButtonsLeft || disable()\"\n [hasToggle]=\"labelConfig.hasToggle\"\n [toggleActive]=\"labelConfig.toggleActive\"\n [toggleDisable]=\"labelConfig.toggleDisable || disable()\"\n [popover]=\"labelConfig.popover\"\n [iconPopoverClass]=\"labelConfig.iconPopoverClass\"\n [onlyShowCount]=\"labelConfig.onlyShowCount\"\n [limitLength]=\"labelConfig.limitLength\"\n [buttonsDescription]=\"labelConfig.buttonsDescription\"\n [disableButtonsDescription]=\"labelConfig.disableButtonsDescription || disable()\"\n [buttonsDescriptionContainerClass]=\"labelConfig.buttonsDescriptionContainerClass\"\n [count]=\"labelConfig.count\" />\n }\n @if (!showValidateBottom()) {\n <ng-container *ngTemplateOutlet=\"templateValidate\"></ng-container>\n }\n <div class=\"libs-ui-checkbox-group {{ horizontal() ? classGroupWhenModeHorizontal() : '' }}\">\n @for (group of groups(); track group) {\n <div [class]=\"horizontal() ? classItemWhenModeHorizontal() : ''\">\n <div class=\"py-[4px] {{ group.item.classIncludeWrapper || '' }}\">\n <libs_ui-components-checkbox-single\n [label]=\"group.item.label || ' '\"\n [checked]=\"group.item.checked || false\"\n [key]=\"group.item[fieldKey()]\"\n [disable]=\"group.disableByKeys || disable() || group.item.disable || false\"\n [disableLabel]=\"group.item.disableLabel || false\"\n [classLabelInclude]=\"classLabelInclude() || group.item.classLabelInclude || ''\"\n [classInclude]=\"classInclude() || group.item.classInclude || ''\"\n [popover]=\"group.item.popover\"\n [avatarConfig]=\"group.item.avatarConfig\"\n [description]=\"group.item.description\"\n [typeLabelPopover]=\"group.item.typeLabelPopover || 'text'\"\n [ignoreShowPopoverLabel]=\"group.item.ignoreShowPopoverLabel || false\"\n [clickExactly]=\"clickExactly()\"\n [modeBorder]=\"modeBorder()\"\n [showBorderError]=\"error() && validRequired()?.hasBorderErrorCheckbox\"\n (outChange)=\"handlerChange($event, group.item)\"\n (outEventPopover)=\"handlerEventPopover($event, group.item)\" />\n </div>\n @if (group.item.checked) {\n @if (group.subText) {\n <div\n class=\"libs-ui-checkbox-group-sub-text libs-ui-font-h7r {{ group.classIncludeSubText || '' }}\"\n [innerHtml]=\"group.subText\"></div>\n }\n <ng-container *ngTemplateOutlet=\"group?.subTemplate || null; context: { item: group.item }\"></ng-container>\n }\n </div>\n }\n </div>\n @if (showValidateBottom()) {\n <ng-container *ngTemplateOutlet=\"templateValidate\"></ng-container>\n }\n</div>\n\n<ng-template #templateValidate>\n @if (error()) {\n <div\n class=\"flex items-center\"\n [class.mb-[8px]]=\"!showValidateBottom()\"\n [class.mt-[8px]]=\"showValidateBottom()\">\n @let constHtmlMessage = validRequired()?.message || ERROR_MESSAGE_EMPTY_VALID;\n <span\n class=\"libs-ui-text-error libs-ui-font-h7r\"\n [innerHtml]=\"constHtmlMessage | translate: validRequired()?.interpolateParams\"></span>\n </div>\n }\n</ng-template>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@libs-ui/components-checkbox-group",
3
- "version": "0.2.356-41",
3
+ "version": "0.2.356-43",
4
4
  "peerDependencies": {
5
5
  "@angular/common": ">=18.0.0",
6
6
  "@angular/core": ">=18.0.0",
7
- "@libs-ui/components-checkbox-single": "0.2.356-41",
8
- "@libs-ui/components-label": "0.2.356-41",
9
- "@libs-ui/components-popover": "0.2.356-41",
10
- "@libs-ui/utils": "0.2.356-41",
7
+ "@libs-ui/components-checkbox-single": "0.2.356-43",
8
+ "@libs-ui/components-label": "0.2.356-43",
9
+ "@libs-ui/components-popover": "0.2.356-43",
10
+ "@libs-ui/utils": "0.2.356-43",
11
11
  "@ngx-translate/core": "^15.0.0",
12
- "@libs-ui/components-avatar": "0.2.356-41",
13
- "@libs-ui/interfaces-types": "0.2.356-41"
12
+ "@libs-ui/components-avatar": "0.2.356-43",
13
+ "@libs-ui/interfaces-types": "0.2.356-43"
14
14
  },
15
15
  "sideEffects": false,
16
16
  "module": "fesm2022/libs-ui-components-checkbox-group.mjs",