@ng-simplicity/forms-core 1.0.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.
- package/LICENSE +21 -0
- package/README.md +188 -0
- package/fesm2022/ng-simplicity-forms-core.mjs +687 -0
- package/fesm2022/ng-simplicity-forms-core.mjs.map +1 -0
- package/index.d.ts +396 -0
- package/package.json +30 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 NG-Simplicity
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# @ng-simplicity/forms-core
|
|
2
|
+
|
|
3
|
+
The core engine package for **NG-Simplicity Forms**. This package manages form states, dynamic registry injection, component lifecycle bindings, and structural layout directives (Rows, Columns, Sections, Groups, Arrays).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Add this package to your Angular application:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @ng-simplicity/forms-core
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Architecture Overview
|
|
18
|
+
|
|
19
|
+
`@ng-simplicity/forms-core` is structured around three primary layers:
|
|
20
|
+
|
|
21
|
+
### 1. The Public Boundary: `NgsFormsService`
|
|
22
|
+
- Injected by the user's component page.
|
|
23
|
+
- Exposes form values and statuses through Signals and observables (e.g. `formValue$`, `dirty`, `isValid`).
|
|
24
|
+
- Provides entry methods like `setFormConfig(config)` and `patchValue(data)`.
|
|
25
|
+
- Implements a retry loading mechanism in case child elements compile asynchronously.
|
|
26
|
+
|
|
27
|
+
### 2. The Internal Coordinator: `NgsFormsInternalService`
|
|
28
|
+
- Provided at the container level by `<ngs-form>`.
|
|
29
|
+
- Coordinates component states, validators, and submission attempts.
|
|
30
|
+
- Offers `subscribeToState(fieldName)` to merge local field configurations with global properties.
|
|
31
|
+
|
|
32
|
+
### 3. Component Registry: `NgsFormsComponentRegistryService`
|
|
33
|
+
- Maps string identifiers (like `input-text`, `input-textarea`) to actual Angular component types.
|
|
34
|
+
- Used by the rendering compiler to dynamically construct layout structures.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Custom Component Development Guide
|
|
39
|
+
|
|
40
|
+
One of the main strengths of `forms-core` is the ability to write your own custom inputs and register them. To build a custom component that hooks into the dynamic forms layout:
|
|
41
|
+
|
|
42
|
+
### 1. Extend `NgsFormsFormItemWithVisibleAndValidatorsBase`
|
|
43
|
+
|
|
44
|
+
Your component must extend the base class and use Angular's Reactive Forms control bindings.
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { Component, ChangeDetectionStrategy, OnInit } from '@angular/core';
|
|
48
|
+
import { ReactiveFormsModule } from '@angular/forms';
|
|
49
|
+
import {
|
|
50
|
+
NgsFormsFormItemWithVisibleAndValidatorsBase,
|
|
51
|
+
NgsFormsFormItem,
|
|
52
|
+
NgsFormsFormItemConfigBaseTextInput
|
|
53
|
+
} from '@ng-simplicity/forms-core';
|
|
54
|
+
import { CommonModule } from '@angular/common';
|
|
55
|
+
import { v4 } from 'uuid';
|
|
56
|
+
|
|
57
|
+
export interface CustomInputConfig extends NgsFormsFormItemConfigBaseTextInput {
|
|
58
|
+
customColor?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@Component({
|
|
62
|
+
selector: 'custom-fancy-input',
|
|
63
|
+
standalone: true,
|
|
64
|
+
imports: [CommonModule, ReactiveFormsModule],
|
|
65
|
+
template: `
|
|
66
|
+
@if (control) {
|
|
67
|
+
<div class="fancy-input-wrapper">
|
|
68
|
+
<label [style.color]="config.customColor">{{ config.label }}</label>
|
|
69
|
+
<input
|
|
70
|
+
[formControl]="control"
|
|
71
|
+
[placeholder]="config.placeholder || ''"
|
|
72
|
+
class="fancy-input-field"
|
|
73
|
+
/>
|
|
74
|
+
@if (errorMessage) {
|
|
75
|
+
<div class="error-msg">{{ errorMessage }}</div>
|
|
76
|
+
}
|
|
77
|
+
</div>
|
|
78
|
+
}
|
|
79
|
+
`,
|
|
80
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
81
|
+
})
|
|
82
|
+
export class CustomFancyInputComponent
|
|
83
|
+
extends NgsFormsFormItemWithVisibleAndValidatorsBase<CustomInputConfig>
|
|
84
|
+
implements OnInit
|
|
85
|
+
{
|
|
86
|
+
static override key = 'fancy-input';
|
|
87
|
+
|
|
88
|
+
// Helper static creator to ensure type-safe schema composition
|
|
89
|
+
static create(config: CustomInputConfig): NgsFormsFormItem<CustomInputConfig> {
|
|
90
|
+
return {
|
|
91
|
+
uuid: v4(),
|
|
92
|
+
type: CustomFancyInputComponent.key,
|
|
93
|
+
config,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 2. Register Your Component
|
|
100
|
+
|
|
101
|
+
Register it into the registry service:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { Component } from '@angular/core';
|
|
105
|
+
import { NgsFormsComponentRegistryService } from '@ng-simplicity/forms-core';
|
|
106
|
+
import { CustomFancyInputComponent } from './custom-fancy-input.component';
|
|
107
|
+
|
|
108
|
+
@Component({
|
|
109
|
+
selector: 'app-root',
|
|
110
|
+
template: '<ngs-form></ngs-form>'
|
|
111
|
+
})
|
|
112
|
+
export class AppComponent {
|
|
113
|
+
constructor(registry: NgsFormsComponentRegistryService) {
|
|
114
|
+
registry.register(CustomFancyInputComponent.key, CustomFancyInputComponent);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 3. Add to Schema
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
const formConfig = {
|
|
123
|
+
inputUpdateDebounce: 100,
|
|
124
|
+
root: NgsFormsFormGroupComponent.create({ name: 'profileForm' }, [
|
|
125
|
+
CustomFancyInputComponent.create({
|
|
126
|
+
name: 'nickname',
|
|
127
|
+
label: 'Nickname',
|
|
128
|
+
placeholder: 'Enter cool nickname...',
|
|
129
|
+
customColor: 'purple'
|
|
130
|
+
})
|
|
131
|
+
])
|
|
132
|
+
};
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Validation & Error Messages (`errorMessageMap`)
|
|
138
|
+
|
|
139
|
+
Each form control component that extends `NgsFormsFormItemWithVisibleAndValidatorsBase` gets access to validation handling out of the box.
|
|
140
|
+
|
|
141
|
+
1. **Defining Validation Rules**: When creating your configuration schema, pass validators (such as `Validators.required` or custom functions) under `validators` or as an observable stream under `validators$`.
|
|
142
|
+
2. **Customizing Error Messages**: Pass an optional `errorMessageMap` object containing key-value pairs matching Angular validator error codes to custom text:
|
|
143
|
+
```typescript
|
|
144
|
+
errorMessageMap: {
|
|
145
|
+
required: 'This field cannot be left blank.',
|
|
146
|
+
minlength: 'Must be at least 4 characters long.',
|
|
147
|
+
email: 'Please enter a valid email address.'
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
3. **Displaying Errors**: Within your custom component template, bind your error display element to the `errorMessage` property inherited from the base class. The core engine dynamically updates `errorMessage` based on whether the control is invalid, touched, dirty, or if the form has been submitted.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Extension Reference Guide
|
|
155
|
+
|
|
156
|
+
When writing custom controls, select the appropriate base class and configuration interface to inherit from.
|
|
157
|
+
|
|
158
|
+
### Available Base Classes
|
|
159
|
+
All base classes are exported from `@ng-simplicity/forms-core`:
|
|
160
|
+
|
|
161
|
+
* **`NgsFormsBaseClassFormComponent<T>`**: The fundamental base class. Automatically fetches and injects the component's static configuration (`config`).
|
|
162
|
+
* **`NgsFormsFormItemWithVisibleAndValidatorsBase<T>`**: Extends the base form component class. Connects the component to the parent `FormGroup` or `FormArray`, listens to visibility state (`visible$`), sets up control validator bindings (`validators`/`validators$`), and manages active `errorMessage` and `submitted` states.
|
|
163
|
+
* **`NgsFormsBaseClassFormInputComponent<T>`**: Extends the validator base class. Exposes a `commonState` signal that listens to merged global state or local state overrides (useful for context properties like theme settings or read-only/interactive display toggles).
|
|
164
|
+
* **`NgsFormsBaseClassFormItemInputWithOptionsComponent<T>`**: Extends the input base class. Specifically designed for controls with choice selection (dropdowns, lists, radio button groups). Exposes a unified `options` signal mapped from either static arrays or dynamic observable streams (`options$`).
|
|
165
|
+
* **`NgsFormsBaseClassItemsContainerBase<T>`**: The base class used for layout containers (like rows, grids, sections, groups) that recursively render a nested set of child form components.
|
|
166
|
+
|
|
167
|
+
### Available Configuration Interfaces
|
|
168
|
+
Ensure your custom configuration type extends one of these core interfaces for full TypeScript safety:
|
|
169
|
+
|
|
170
|
+
* **`NgsFormsFormItemConfigBase`**: Standard base structure containing only an optional `uuid?: string`.
|
|
171
|
+
* **`NgsFormsFormItemConfigBaseItemWithNameAndValidators`**: Core interface for registerable form controls. Adds `name: string`, `errorMessageMap?: NgsFormsFormErrorKeyValueMap`, `disabled?`/`disabled$?`, and `validators?`/`validators$?`.
|
|
172
|
+
* **`NgsFormsFormItemConfigBaseInput`**: Extends the name/validators base. Adds common interactive input properties: `id?: string`, `label: string`, and `value?: unknown`.
|
|
173
|
+
* **`NgsFormsFormItemConfigBaseTextInput`**: Extends the input base. Adds text-specific options: `placeholder?: string` and `type?: 'text' | 'email' | 'password'`.
|
|
174
|
+
* **`NgsFormsFormItemConfigBaseInputWithOptions`**: Extends the input base. Adds selection fields: `options?: Array<NgsFormsFormInputOption>` and `options$?: Observable<Array<NgsFormsFormInputOption>>`.
|
|
175
|
+
* **`NgsFormsFormItemContainerConfigBase`**: Extends the base interface. Used by layout components, defining an array of children: `items: Array<NgsFormsFormItem<any>>`.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Commands
|
|
180
|
+
|
|
181
|
+
- **Run unit tests**:
|
|
182
|
+
```bash
|
|
183
|
+
nx test forms-core
|
|
184
|
+
```
|
|
185
|
+
- **Run test with code coverage**:
|
|
186
|
+
```bash
|
|
187
|
+
nx test forms-core --codeCoverage
|
|
188
|
+
```
|