npm package: @libs-ui/components-radio-group
Description: > Component hiển thị nhóm các lựa chọn Radio buttons, hỗ trợ layout ngang/dọc, validation và custom template.
Latest version: 0.2.356-23

# @libs-ui/components-radio-group

> Component hiển thị nhóm các lựa chọn Radio buttons, hỗ trợ layout ngang/dọc, validation và custom template.

## Giới thiệu

`LibsUiComponentsRadioGroupComponent` là một standalone Angular component cho phép người dùng chọn một mục duy nhất từ một danh sách các tuỳ chọn. Component này được thiết kế để thay thế cho thẻ `<input type="radio">` mặc định, với nhiều tính năng nâng cao như validation, cấu hình label chung, hỗ trợ template tuỳ chỉnh, và layout linh hoạt.

### Tính năng

- ✅ **Flexible Layout**: Hỗ trợ hiển thị theo chiều dọc (mặc định) hoặc chiều ngang (`horizontal`).
- ✅ **Rich Content**: Hỗ trợ hiển thị Label, Description, Sub-text, và Custom Template cho từng item.
- ✅ **Validation Support**: Tích hợp validation `required` và hiển thị thông báo lỗi.
- ✅ **Global Config**: Cấu hình chung cho toàn bộ group (disable, label, class).
- ✅ **Reactive**: Tích hợp chặt chẽ với Angular Signals và Forms.
- ✅ **Control API**: Cung cấp API để kiểm soát validation và reset state từ bên ngoài.

## Khi nào sử dụng

- Khi người dùng cần chọn chính xác một tùy chọn trong danh sách.
- Thay thế cho dropdown khi số lượng tùy chọn ít (dưới 5) để người dùng có thể nhìn thấy tất cả các lựa chọn ngay lập tức.
- Cần hiển thị chi tiết phụ (sub-text) mô tả cho từng tùy chọn để giúp người dùng ra quyết định.

## Cài đặt

```bash
# npm
npm install @libs-ui/components-radio-group

# yarn
yarn add @libs-ui/components-radio-group
```

## Import

```typescript
import { LibsUiComponentsRadioGroupComponent } from '@libs-ui/components-radio-group';

@Component({
  standalone: true,
  imports: [LibsUiComponentsRadioGroupComponent],
  // ...
})
export class YourComponent {}
```

## Ví dụ

### Basic Usage

```html
<libs_ui-components-radio-group
  [groups]="groups()"
  (outChange)="onChange($event)" />
```

```typescript
readonly groups = signal<IRadioGroupItem[]>([
  { item: { key: 'opt1', label: 'Option 1', active: true } },
  { item: { key: 'opt2', label: 'Option 2', active: false } }
]);
```

### With Validation & Label

```html
<libs_ui-components-radio-group
  [groups]="groups()"
  [labelConfig]="{ labelLeft: 'Choose Plan', required: true }"
  [validRequired]="{ message: 'Plan is required' }"
  (outFunctionsControl)="control = $event" />
```

## API

### libs_ui-components-radio-group

#### Inputs

| Property                      | Type                     | Default      | Description                                                   |
| ----------------------------- | ------------------------ | ------------ | ------------------------------------------------------------- |
| `[groups]`                    | `Array<IRadioGroupItem>` | `[]`         | Danh sách các nhóm radio buttons (Model Input).               |
| `[keyActive]`                 | `unknown`                | `undefined`  | Giá trị key của item đang active (để set initial state).      |
| `[fieldKey]`                  | `string`                 | `'key'`      | Tên property dùng làm key định danh trong item.               |
| `[keysDisable]`               | `Array<string>`          | `undefined`  | Danh sách các keys bị disable.                                |
| `[horizontal]`                | `boolean`                | `false`      | Hiển thị theo chiều ngang.                                    |
| `[disable]`                   | `boolean`                | `false`      | Vô hiệu hóa toàn bộ group.                                    |
| `[labelConfig]`               | `ILabel`                 | `undefined`  | Cấu hình label cho toàn bộ group.                             |
| `[validRequired]`             | `{ message?: string }`   | `undefined`  | Cấu hình validation bắt buộc chọn.                            |
| `[typeRadio]`                 | `'normal' \| 'medium'`   | `'normal'`   | Kích thước của radio (mặc định cho cả group).                 |
| `[alwaysShowSubText]`         | `boolean`                | `false`      | Luôn hiển thị sub-text của item.                              |
| `[ignoreClassMarginLastItem]` | `boolean`                | `false`      | Ẩn class margin cho item cuối cùng.                           |
| `[horizontalClassInclude]`    | `string`                 | `''`         | Class margin cho item trong chế độ horizontal.                |
| `[classInclude]`              | `string`                 | `''`         | Custom class cho từng radio trong group.                      |
| `[classLabelInclude]`         | `string`                 | `''`         | Custom class cho label của từng radio.                        |
| `[classItemInclude]`          | `string`                 | `'py-[4px]'` | Class cho từng item wrapper.                                  |
| `[clickExactly]`              | `boolean`                | `true`       | Yêu cầu click chính xác vào radio (true) hay cả dòng (false). |

#### Outputs

| Property                | Type                              | Description                                                            |
| ----------------------- | --------------------------------- | ---------------------------------------------------------------------- |
| `(outChange)`           | `IRadioEvent`                     | Emit khi người dùng thay đổi lựa chọn.                                 |
| `(outClickButton)`      | `IButton`                         | Emit khi click vào button trong label config (nếu có).                 |
| `(outFunctionsControl)` | `IRadioGroupFunctionControlEvent` | Emit object chứa các hàm điều khiển (checkIsValid, reset, resetError). |

#### Interfaces

**IRadioGroupItem**

| Property              | Type          | Description                                                    |
| --------------------- | ------------- | -------------------------------------------------------------- |
| `item`                | `IRadioItem`  | Object chứa thông tin chính của radio (key, label, active...). |
| `subText`             | `string`      | Text phụ hiển thị dưới radio.                                  |
| `classIncludeSubText` | `string`      | Class cho text phụ.                                            |
| `subTemplate`         | `TemplateRef` | Template custom hiển thị dưới radio.                           |
| `disableByKeys`       | `boolean`     | Disable item dựa trên keysDisable input.                       |

**IRadioGroupFunctionControlEvent**

| Method           | Description                                                                              |
| ---------------- | ---------------------------------------------------------------------------------------- |
| `checkIsValid()` | Kiểm tra validation `required` và hiển thị lỗi nếu chưa chọn. Trả về `Promise<boolean>`. |
| `resetError()`   | Xóa trạng thái lỗi.                                                                      |
| `reset()`        | Reset toàn bộ selection về trạng thái ban đầu và xóa lỗi.                                |

## Công nghệ

| Technology      | Version | Purpose          |
| --------------- | ------- | ---------------- |
| Angular         | 18+     | Framework        |
| Angular Signals | -       | State management |
| OnPush          | -       | Change Detection |

## Demo

```bash
npx nx serve core-ui
```

Truy cập path: `/components/radio/group`