@rxdi/forms 0.7.217 → 0.7.219
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 +73 -5
- package/dist/form.array.d.ts +2 -1
- package/dist/form.array.js +23 -1
- package/dist/form.group.js +9 -4
- package/dist/form.tokens.d.ts +2 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -200,11 +200,10 @@ export class TagsComponent extends LitElement {
|
|
|
200
200
|
model: 'tags', // Triggers form.patchValue(this.tags) on INIT
|
|
201
201
|
})
|
|
202
202
|
form = new FormGroup({
|
|
203
|
-
tags: new FormArray<{ value: string }>(
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}),
|
|
203
|
+
tags: new FormArray<{ value: string }>(
|
|
204
|
+
[],
|
|
205
|
+
(value) => new FormGroup({ value: value.value || value }) // Factory handles population automatically
|
|
206
|
+
),
|
|
208
207
|
});
|
|
209
208
|
|
|
210
209
|
addTag() {
|
|
@@ -223,6 +222,75 @@ export class TagsComponent extends LitElement {
|
|
|
223
222
|
|
|
224
223
|
````
|
|
225
224
|
|
|
225
|
+
### Typed Subscriptions & Virtual Inputs
|
|
226
|
+
|
|
227
|
+
You can subscribe to `valueChanges` on individual inputs, even if they aren't in the DOM yet!
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
// Works even if 'email' input is inside an *ngIf or not yet rendered
|
|
231
|
+
this.form.get('email').valueChanges.subscribe(value => {
|
|
232
|
+
console.log('Email changed:', value); // 'value' is strongly typed!
|
|
233
|
+
});
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
This is powered by "Virtual Inputs" which mock the input interface if the model key exists but the DOM element is missing.
|
|
237
|
+
|
|
238
|
+
### Working with Value Changes
|
|
239
|
+
|
|
240
|
+
The `valueChanges` observable is powerful for creating interactive forms.
|
|
241
|
+
|
|
242
|
+
#### 1. Debounced Search
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
|
246
|
+
|
|
247
|
+
this.form.get('search').valueChanges.pipe(
|
|
248
|
+
debounceTime(300),
|
|
249
|
+
distinctUntilChanged()
|
|
250
|
+
).subscribe(term => {
|
|
251
|
+
this.searchService.search(term);
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### 2. Dependant Fields (Cascading Dropdowns)
|
|
256
|
+
|
|
257
|
+
Reset or modify dependent fields when a parent field changes.
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
this.form.get('country').valueChanges.subscribe(country => {
|
|
261
|
+
// Reset state when country changes
|
|
262
|
+
this.form.get('state').value = '';
|
|
263
|
+
|
|
264
|
+
// Update state options dynamically based on country
|
|
265
|
+
this.loadStatesFor(country);
|
|
266
|
+
});
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
#### 3. Dynamic Disabling
|
|
270
|
+
|
|
271
|
+
Disable controls based on the value of others.
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
this.form.get('subscribeNewsletter').valueChanges.subscribe(shouldSubscribe => {
|
|
275
|
+
const emailControl = this.form.get('newsletterEmail');
|
|
276
|
+
if (shouldSubscribe) {
|
|
277
|
+
emailControl.disabled = false;
|
|
278
|
+
} else {
|
|
279
|
+
emailControl.disabled = true;
|
|
280
|
+
emailControl.value = ''; // Optional: clear value
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Generic Typed AbstractInput
|
|
286
|
+
|
|
287
|
+
`AbstractInput` is now generic, propagating types through the form.
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
const emailInput: AbstractInput<string> = this.form.get('email');
|
|
291
|
+
// emailInput.value is string
|
|
292
|
+
```
|
|
293
|
+
|
|
226
294
|
## API Reference
|
|
227
295
|
|
|
228
296
|
### Validators
|
package/dist/form.array.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export declare class FormArray<T = any> implements AbstractControl<T[]> {
|
|
|
16
16
|
private form;
|
|
17
17
|
private options;
|
|
18
18
|
private subscriptions;
|
|
19
|
-
constructor(controls?: AbstractControl<T>[], nameOrOptions?: string | FormArrayOptions<T>);
|
|
19
|
+
constructor(controls?: AbstractControl<T>[], nameOrOptions?: string | FormArrayOptions<T> | ((value: T) => AbstractControl));
|
|
20
20
|
get value(): T[];
|
|
21
21
|
getOptions(): FormArrayOptions<T>;
|
|
22
22
|
setOptions(options: FormOptions): void;
|
|
@@ -32,4 +32,5 @@ export declare class FormArray<T = any> implements AbstractControl<T[]> {
|
|
|
32
32
|
getParentElement(): LitElement;
|
|
33
33
|
set value(values: T[]);
|
|
34
34
|
patchValue(values: T[]): void;
|
|
35
|
+
updateValueAndValidity(): Promise<any[]>;
|
|
35
36
|
}
|
package/dist/form.array.js
CHANGED
|
@@ -23,8 +23,10 @@ class FormArray {
|
|
|
23
23
|
if (typeof nameOrOptions === 'string') {
|
|
24
24
|
this.name = nameOrOptions;
|
|
25
25
|
}
|
|
26
|
+
else if (typeof nameOrOptions === 'function') {
|
|
27
|
+
this.options = { itemFactory: nameOrOptions };
|
|
28
|
+
}
|
|
26
29
|
else {
|
|
27
|
-
this.name = nameOrOptions.name || '';
|
|
28
30
|
this.options = nameOrOptions;
|
|
29
31
|
}
|
|
30
32
|
this._valueChanges = new rxjs_1.BehaviorSubject(this.value);
|
|
@@ -136,5 +138,25 @@ class FormArray {
|
|
|
136
138
|
});
|
|
137
139
|
this.updateValue();
|
|
138
140
|
}
|
|
141
|
+
updateValueAndValidity() {
|
|
142
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
143
|
+
this.valid = true;
|
|
144
|
+
this.invalid = false;
|
|
145
|
+
this.errors = {};
|
|
146
|
+
const errors = [];
|
|
147
|
+
for (const [index, control] of this.controls.entries()) {
|
|
148
|
+
if (control.updateValueAndValidity) {
|
|
149
|
+
const result = yield control.updateValueAndValidity();
|
|
150
|
+
if (control.invalid) {
|
|
151
|
+
this.valid = false;
|
|
152
|
+
this.invalid = true;
|
|
153
|
+
this.errors[index] = result;
|
|
154
|
+
errors.push(...result);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return errors;
|
|
159
|
+
});
|
|
160
|
+
}
|
|
139
161
|
}
|
|
140
162
|
exports.FormArray = FormArray;
|
package/dist/form.group.js
CHANGED
|
@@ -121,17 +121,22 @@ class FormGroup {
|
|
|
121
121
|
this.setElementDirty(i);
|
|
122
122
|
return yield this.validate(i);
|
|
123
123
|
})));
|
|
124
|
+
const inputsWithErrors = inputs.filter((e) => e.errors.length);
|
|
125
|
+
const nestedErrors = [];
|
|
124
126
|
for (const [key, control] of this.controls.entries()) {
|
|
125
127
|
if (control.updateValueAndValidity) {
|
|
126
|
-
yield control.updateValueAndValidity();
|
|
128
|
+
const result = (yield control.updateValueAndValidity());
|
|
127
129
|
if (control.invalid) {
|
|
128
130
|
this.invalid = true;
|
|
129
131
|
this.valid = false;
|
|
132
|
+
if (Array.isArray(result)) {
|
|
133
|
+
nestedErrors.push(...result);
|
|
134
|
+
}
|
|
130
135
|
}
|
|
131
136
|
}
|
|
132
137
|
}
|
|
133
138
|
this.getParentElement().requestUpdate();
|
|
134
|
-
return
|
|
139
|
+
return [...inputsWithErrors, ...nestedErrors];
|
|
135
140
|
});
|
|
136
141
|
}
|
|
137
142
|
updateValueAndValidityOnEvent(method) {
|
|
@@ -423,8 +428,8 @@ class FormGroup {
|
|
|
423
428
|
}
|
|
424
429
|
Object.keys(value).forEach((key) => {
|
|
425
430
|
const control = this.controls.get(key);
|
|
426
|
-
if (control === null || control === void 0 ? void 0 : control
|
|
427
|
-
control
|
|
431
|
+
if (control === null || control === void 0 ? void 0 : control.patchValue) {
|
|
432
|
+
control.patchValue(value[key]);
|
|
428
433
|
}
|
|
429
434
|
else {
|
|
430
435
|
this.setValue(key, value[key]);
|
package/dist/form.tokens.d.ts
CHANGED
|
@@ -50,6 +50,8 @@ export interface AbstractControl<T = any> {
|
|
|
50
50
|
name?: string;
|
|
51
51
|
push?(control: AbstractControl): void;
|
|
52
52
|
getFormElement?(): HTMLFormElement;
|
|
53
|
+
patchValue?(value: T): void;
|
|
54
|
+
get?(name: string): any;
|
|
53
55
|
}
|
|
54
56
|
export type ValidatorFn = (element: AbstractInput | HTMLInputElement) => Promise<InputErrorMessage | void> | InputErrorMessage | void;
|
|
55
57
|
export interface FormInputOptions {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rxdi/forms",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.219",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"author": "Kristiyan Tachev",
|
|
6
6
|
"license": "MIT",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"build": "tsc"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@rxdi/lit-html": "^0.7.
|
|
15
|
+
"@rxdi/lit-html": "^0.7.218",
|
|
16
16
|
"@types/node": "^25.0.3",
|
|
17
17
|
"rxjs": "^7.8.2",
|
|
18
18
|
"typescript": "^5.9.3"
|