npm package: @nqood/nq-primeng-form
Description: Dynamic PrimeNG form library for Angular
Latest version: 1.0.23

# @nqood/nq-primeng-form

Dynamic, type-safe form builder for Angular using PrimeNG. Define forms with configuration objects; get full TypeScript support, validation, and automatic rendering.

## Table of Contents
- [Features](#features)
- [Installation](#installation)
- [Styles & Grid System](#styles--grid-system)
- [Changelog](#changelog)
- [Dynamic Form](#dynamic-form)
- [Core API Reference](#core-api-reference)
  - [IFormGroup](#iformgroup)
  - [IFormControl](#iformcontrol)
  - [IFormArray](#iformarray)
  - [IFormInputGroup](#iforminputgroup)
- [Advanced Usage](#advanced-usage)
  - [Custom Templates](#custom-templates)
  - [Dynamic Dependencies (updateOnChange)](#dynamic-dependencies-updateonchange)
  - [View-Only Mode](#view-only-mode)
- [Component API](#component-api)
- [License](#license)

---

## Features

- **Type-safe** – Full TypeScript support for form values and controls.
- **Declarative** – Define forms as objects, let the component handle the rendering.
- **PrimeNG Integrated** – Uses PrimeNG components for all inputs.
- **Validation** – Built-in support for Angular validators with automatic error message display.
- **Responsive Grid** – Built-in grid system (Bootstrap/Tailwind compatible).
- **Nested Forms** – Support for nested `IFormGroup`, `IFormArray`, and `IFormInputGroup`.

---

## Installation

```bash
npm install @nqood/nq-primeng-form
```

Ensure peer dependencies are installed:
```bash
npm install @angular/forms primeng primeicons
```

---

## Styles & Grid System

The library uses **SCSS** for its internal grid and component styling.

### 1. Import Styles
Import in your global `styles.scss`:
```scss
@import "@nqood/nq-primeng-form/style.scss";
```

### 2. The Internal Grid
If you don't provide a `formClass`, the component uses its own internal grid system:
- **Wrapper Class:** `dynamic-form-grid`
- **Default Columns:** 1 on mobile, 2 on tablet (`md`), 3 on desktop (`lg`).
- **Control Classes:** Use `col-md-6`, `col-lg-4`, etc., in the control config to define widths.

**Example with Bootstrap/Internal Grid:**
```typescript
new IFormControl({
  type: FormControlType.Text,
  label: 'Name',
  class: 'col-md-6' // Occupies 50% width on medium screens
})
```

---

## Changelog

See `CHANGELOG.md`.

---

## Dynamic Form

The **dynamic form** is the main entry point: the `nq-primeng-form` component renders a form from an `IFormGroup` configuration. You define the structure (controls, groups, arrays) and options in code; the component handles layout, validation display, and two-way binding.

### Basic usage

1. Build a form model with `IFormGroup`, `IFormControl`, and optionally `IFormArray` or `IFormInputGroup` (see [Core API Reference](#core-api-reference)).
2. Bind the model to the component with the `form` input.
3. Optionally set `formClass`, `showLabels`, `layout`, `viewOnly`, `loading`, or `useIftaLabel`.

```typescript
import { IFormGroup, IFormControl } from '@nqood/nq-primeng-form';
import { FormControlType } from '@nqood/nq-primeng-form';
import { Validators } from '@angular/forms';

const form = new IFormGroup({
  name: new IFormControl({
    type: FormControlType.Text,
    label: 'Name',
    placeholder: 'Enter name',
    validators: [Validators.required],
  }),
  email: new IFormControl({
    type: FormControlType.Text,
    label: 'Email',
    validators: [Validators.required, Validators.email],
  }),
});
```

```html
<nq-primeng-form
  [form]="form"
  [formClass]="'row g-3'"
  [showLabels]="true"
  [layout]="'vertical'"
  [viewOnly]="false"
  [loading]="loading()"
  [useIftaLabel]="false"
></nq-primeng-form>
```

To get values or validate, use the form instance:

```typescript
const raw = form.getRawValue();
const { isValid, message } = form.validateForm();
form.patchValue({ name: 'Updated' });
```

### Dynamic form component options

| Input | Type | Default | Description |
|-------|------|---------|-------------|
| `form` | `IFormGroup` | (required) | The form model instance. |
| `formClass` | `string` | `'row g-3'` | CSS class for the form wrapper (e.g. grid). |
| `showLabels` | `boolean` | `true` | Show labels for all controls. |
| `layout` | `'horizontal' \| 'vertical'` | `'vertical'` | Label/control layout. |
| `viewOnly` | `boolean` | `false` | Renders the whole form as read-only (values as text). |
| `loading` | `boolean` | `false` | Shows a form-wide loading overlay. |
| `useIftaLabel` | `boolean` | `false` | Use PrimeNG Ifta (float) label behavior. |

Control-level options (e.g. `hidden`, `viewOnly`, `validators`, `options`, type-specific configs) are set on each `IFormControl` / `IFormGroup` / `IFormArray` in the model; see [IFormControl](#iformcontrol), [IFormGroup](#iformgroup), and [IFormArray](#iformarray).

---

## Core API Reference

### IFormGroup
Extends Angular's `FormGroup`. Used as the root form or for nested sections.

#### Configuration (`IFormGroupConfig`)
| Property | Type | Description |
|---|---|---|
| `label` | `string` | Optional title displayed above the group. |
| `class` | `string` | CSS class for the group wrapper. |
| `formClass` | `string` | Grid class for the group's children (e.g., `row g-3`). |
| `viewOnly` | `boolean` | Sets the entire group to read-only mode. |
| `hidden` | `boolean` | Hides the entire group. |
| `updateOnChange` | `Array` | List of dependencies between fields (see Advanced Usage). |

#### Methods
- **`validateForm()`**: Marks all controls as touched and returns validity.
  ```typescript
  const { isValid, message } = form.validateForm();
  ```
- **`getRawValue()`**: Returns the typed value of the entire form.
- **`patchValue(value)`**: Type-safe method to update form values.
- **`updateConfig(partialConfig)`**: Updates the group's configuration on the fly.
- **`updateControlConfigs(configs)`**: Updates multiple nested control configurations at once.
  ```typescript
  form.updateControlConfigs({
    email: { hidden: true, validators: [] }
  });
  ```

---

### IFormControl
Extends Angular's `FormControl`. Represents a single input field.

#### Configuration (`IFormControlConfig`)
| Property | Type | Description |
|---|---|---|
| `type` | `FormControlType` | Required. The input type (Text, Select, Date, etc.). |
| `label` | `string` | Field label (supports translation keys). |
| `placeholder` | `string` | Input placeholder. |
| `validators` | `ValidatorFn[]` | Angular validators. |
| `class` | `string` | Grid column class (e.g., `col-md-6`). |
| `options` | `Signal` | Options for Select, MultiSelect, Radio, or Autocomplete. |
| `actionButton` | `Object` | Optional button rendered inside the control's row. |
| `viewOnly` | `boolean` | Renders value as text instead of an input. |
| `loading` | `Signal` | Shows a loading spinner inside the control. |

#### Type-specific options

Use these on `IFormControlConfig` for the corresponding control types.

##### TextArea — `textareaConfigs`
| Property | Type | Description |
|---|---|---|
| `autoResize` | `boolean` | When true, textarea grows with content. |
| `rows` | `number` | Initial number of visible rows. |

##### Date / YearMonth / Year / Time — `dataOptions`
| Property | Type | Description |
|---|---|---|
| `minDate` | `Date` | Minimum selectable date. |
| `maxDate` | `Date` | Maximum selectable date. |
| `dateFormat` | `string` | Format string for the date value. |
| `dateFormatView` | `string` | Format string for the date picker display. |
| `showIcon` | `boolean` | Show calendar/clock icon. |
| `showClear` | `boolean` | Show clear button. |
| `disabledDates` | `Date[]` | Dates that cannot be selected. |
| `showTime` | `boolean` | Include time in date picker. |
| `hourFormat` | `'12' \| '24'` | 12- or 24-hour format. |
| `iconDisplay` | `'button' \| 'input'` | Where the icon is shown. |

##### Text / Number / Password — `textInputConfigs`
| Property | Type | Description |
|---|---|---|
| `maxLength` | `number` | Max character length. |
| `minLength` | `number` | Min character length. |
| `pattern` | `string` | Pattern for the input. |

##### Number — `numberInputConfigs`
| Property | Type | Description |
|---|---|---|
| `mode` | `'decimal' \| 'currency'` | Mode for the number input. |
| `min` | `number` | Min value. |
| `max` | `number` | Max value. |
| `minFractionDigits` | `number` | Min fraction digits. |
| `maxFractionDigits` | `number` | Max fraction digits. |
| `currency` | `string` | Currency for the number input. |
| `locale` | `string` | Locale for the number input. |

##### Radio — `radioOptions`
| Property | Type | Description |
|---|---|---|
| `radioInlineWithLabel` | `boolean` | Render radios inline with option labels. |
| `radioLabelClass` | `string` | CSS class for each radio option label. |
| `radioGroupClass` | `string` | CSS class for the radio group wrapper. |

##### Checkbox — `checkboxOptions`
| Property | Type | Description |
|---|---|---|
| `labelClass` | `string` | CSS class for the checkbox label. |
| `binaryLabel` | `string` | Label text used when the checkbox is in binary mode. |

**Note:** When `type` is `FormControlType.Checkbox` and `options` is not provided, the control behaves as a single binary checkbox (`true` / `false`) by default.

##### Switch — `SwitchOptions`
| Property | Type | Description |
|---|---|---|
| `CheckedText` | `string` | Label when switch is on. |
| `UncheckedText` | `string` | Label when switch is off. |

#### Methods
- **`updateConfig(partialConfig)`**: Updates control settings (validators, visibility, etc.).
- **`setOptions(options)`**: Programmatically updates the options signal.
- **`showLoader()` / `hideLoader()`**: Toggles the internal loading state.

---

### IFormArray
Extends Angular's `FormArray`. Used for dynamic, repeatable lists of items.

#### Configuration (`IFormArrayConfig`)
| Property | Type | Description |
|---|---|---|
| `template` | `() => IFormGroup` | **Required**. Function that returns the model for a new item. |
| `label` | `string` | Label for the array section. |
| `itemLabel` | `string` | Label template for each item (e.g. "Item : 1"). |
| `minItems` / `maxItems` | `number` | Minimum/maximum number of items. |
| `addButtonText` | `string` | Label for the "Add" button. |
| `removeButtonText` | `string` | Label for remove button (e.g. tooltip). |
| `hideAddButton` | `boolean` | Hides the add button. |
| `hideRemoveButton` | `boolean` | Hides remove buttons on items. |
| `formsWrapperClass` | `string` | CSS class for the array wrapper. |
| `formClass` | `string` | Grid/layout class for item content. |
| `itemBorderClass` | `string` | CSS class for each item container. |
| `addButtonStyle` | `object` | `{ severity, outlined, icon?, position? }` for add button. |
| `noItemsText` | `string` | Text when array is empty. |
| `disabled` | `boolean` | Disables the array (add/remove/inputs). |
| `hidden` | `boolean` | Hides the entire array. |
| `dividerBefore` / `dividerAfter` | `IFormDividerConfig` | Optional dividers. |
| `onItemsChange` | `(formArray) => void` | Callback when items are added or removed. |

#### Methods
- **`addItem(value?)`**: Appends a new item to the list.
- **`removeItem(index)`**: Removes an item while respecting `minItems`.
- **`setItems(values)`**: Clears the list and populates it with new values.
- **`clearItems()`**: Removes all items.

---

### IFormInputGroup
A specialized `IFormGroup` where all nested controls are rendered inside a single PrimeNG `p-input-group`.

```typescript
new IFormInputGroup({
  amount: new IFormControl({ type: FormControlType.Number }),
  currency: new IFormControl({ type: FormControlType.Select, options: currencies })
}, {
  label: 'Price',
  class: 'col-md-4'
})
```

---

## Advanced Usage

### Custom Templates
Inject custom components or HTML into the form flow.

```typescript
// 1. Define in config
myCustomField: new IFormControl({
  type: FormControlType.CustomTemplate,
  templateId: 'user-header'
})
```

```html
<!-- 2. Use in HTML -->
<nq-primeng-form [form]="form">
  <div templateId="user-header">
    <h3>Custom Section Header</h3>
    <hr />
  </div>
</nq-primeng-form>
```

### Dynamic Dependencies (`updateOnChange`)
Automatically handle logic when a field value changes.

```typescript
const form = new IFormGroup({
  country: new IFormControl({ type: FormControlType.Select, options: countries }),
  city: new IFormControl({ type: FormControlType.Select, options: signal([]) })
}, {
  updateOnChange: [
    {
      target: 'country',
      callback: (group) => {
        const country = group.controls.country.value;
        // Logic to update city options based on country selection
        group.controls.city.updateConfig({ disabled: !country });
      }
    }
  ]
});
```

### View-Only Mode
Switch any part of the form to a read-only state. Values will render as plain text using `p-inputtext` styling but without the input behavior.

---

## Component API

The `nq-primeng-form` component inputs are documented in [Dynamic form component options](#dynamic-form-component-options) above.

---

## License
MIT