npm package: @libs-ui/pipes-convert-signal-to-object
Description: > Version: `0.2.355-15` > > Pipe chuyển đổi cấu trúc Signals lồng nhau thành plain object/value.
Latest version: 0.2.356-23

# @libs-ui/pipes-convert-signal-to-object

> Version: `0.2.355-15`
>
> Pipe chuyển đổi cấu trúc Signals lồng nhau thành plain object/value.

## Giới thiệu

`LibsUiPipesConvertSignalToObjectPipe` là pipe ngược lại của `convert-object-to-signal`. Nó nhận vào một cấu trúc nested signals (object hoặc array chứa các signals) và unwrap toàn bộ chúng thành plain object/array. Điều này rất hữu ích khi bạn cần chuẩn bị dữ liệu để gửi đi (API call), lưu trữ (LocalStorage), hoặc sử dụng với các thư viện không hỗ trợ Signal.

### Tính năng

- ✅ Unwrap nested signals (multi-level)
- ✅ Chuyển đổi Signal Object thành Plain Object
- ✅ Chuyển đổi Signal Array thành Plain Array
- ✅ Deep clone kết quả mặc định (an toàn)
- ✅ Hỗ trợ primitive signals

## Khi nào sử dụng

### 📤 Gửi data đến API

Các HTTP client thường yêu cầu plain object. Pipe này giúp bạn chuẩn bị payload dễ dàng:

```typescript
// Nested signals state
const user = {
  name: signal('John'),
  settings: { theme: signal('dark') },
};

// Convert to plain object
const payload = user | LibsUiPipesConvertSignalToObjectPipe;
// => { name: 'John', settings: { theme: 'dark' } }

http.post('/api/user', payload);
```

### 💾 Serialize đến LocalStorage

Signal không thể được serialize trực tiếp bằng `JSON.stringify`. Hãy convert chúng trước:

```typescript
const plainData = dataSignal | LibsUiPipesConvertSignalToObjectPipe;
localStorage.setItem('data', JSON.stringify(plainData));
```

### 🔌 Tích hợp External Libraries

Nhiều thư viện (charting, maps, etc.) chỉ chấp nhận plain JS objects/arrays:

```typescript
const chartData = signalsData | LibsUiPipesConvertSignalToObjectPipe;
chart.update(chartData);
```

## Cài đặt

```bash
npm install @libs-ui/pipes-convert-signal-to-object
```

## Import

```typescript
import { LibsUiPipesConvertSignalToObjectPipe } from '@libs-ui/pipes-convert-signal-to-object';

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

## Ví dụ

### 1. Basic Object Unwrap

```html
@let user = (userSignal | LibsUiPipesConvertSignalToObjectPipe);

<p>User: {{ user.name }}</p>
```

### 2. Array Unwrap

```html
@let items = (itemsSignal | LibsUiPipesConvertSignalToObjectPipe);

<ul>
  @for (item of items; track $index) {
  <li>{{ item }}</li>
  }
</ul>
```

### 3. No Clone (Faster)

Nếu bạn chắc chắn không mutate kết quả hoặc cần performance tối đa:

```html
@let rawData = (dataSignal | LibsUiPipesConvertSignalToObjectPipe : false);
```

## API

### LibsUiPipesConvertSignalToObjectPipe

```typescript
data | LibsUiPipesConvertSignalToObjectPipe : isCloneDeep?
```

#### Parameters

| Property      | Type                   | Default | Description                                               |
| ------------- | ---------------------- | ------- | --------------------------------------------------------- |
| `data`        | `any`                  | -       | Nested signals cần chuyển đổi thành plain object.         |
| `isCloneDeep` | `boolean \| undefined` | `true`  | `true` để deep clone (an toàn), `false` để giữ reference. |

#### Returns

Plain object, array, hoặc primitive value sau khi đã unwrap tất cả signals.

## Hidden Logic

### 1. 🔄 Recursive Unwrap

Pipe sẽ đệ quy đi vào mọi property của object/array. Nếu gặp Signal, nó sẽ gọi `()` để lấy giá trị, sau đó tiếp tục đệ quy cho giá trị đó.

### 2. 🔀 Deep Clone

Mặc định, kết quả trả về là một bản sao deep clone của dữ liệu đã unwrap. Điều này đảm bảo rằng nếu bạn thay đổi property của object kết quả, nó **KHÔNG** ảnh hưởng ngược lại đến state trong Signal gốc.

## Demo

- **Local Development**: [http://localhost:4500/pipes/convert-signal-to-object](http://localhost:4500/pipes/convert-signal-to-object)

## Unit Tests

Xem file `test-commands.md` để biết cách chạy unit tests.

## License

MIT