@rxdi/forms 0.7.229 → 0.7.231

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 CHANGED
@@ -327,17 +327,17 @@ function ErrorTemplate(input: AbstractInput) {
327
327
 
328
328
  ### 1. Grouping Multiple Inputs (Checkbox Groups)
329
329
 
330
- By default, inputs with the same `name` attribute are treated as a single value (last write wins). However, for checkboxes, you often want an array of values.
330
+ By default (`multi: false`), inputs with the same `name` attribute behave like radio buttons (single selection). To allow multiple selections (array of values), set `multi: true` in the form options.
331
331
 
332
332
  **Scenario:** A list of permissions where multiple can be selected.
333
333
 
334
334
  ```typescript
335
335
  @Form({
336
336
  name: 'permissions-form',
337
- multi: true // Enable multi-value binding for same-name inputs
337
+ multi: true // Enable multi-value binding for SAME-NAME inputs
338
338
  })
339
339
  form = new FormGroup({
340
- roles: [] // Will be an array of values
340
+ roles: [] // Will be an array of values ['admin', 'viewer']
341
341
  });
342
342
  ```
343
343
 
@@ -347,19 +347,17 @@ form = new FormGroup({
347
347
  <label> <input name="roles" type="checkbox" value="viewer" /> Viewer </label>
348
348
  ```
349
349
 
350
- If the user checks "Admin" and "Viewer", `form.value.roles` will be `['admin', 'viewer']`.
350
+ ### 2. Single Selection Checkbox (Default Behavior)
351
351
 
352
- ### 2. Single Selection Checkbox (Radio Behavior with Checkboxes)
353
-
354
- If you want multiple checkboxes to act like a radio button (only one valid at a time) but with uncheck capability:
352
+ If you want multiple checkboxes to act like a radio button (only one valid at a time) but with uncheck capability, simply use the default `multi: false`.
355
353
 
356
354
  ```typescript
357
355
  @Form({
358
356
  name: 'settings-form',
359
- multi: false // Default behavior
357
+ // multi: false // Default behavior
360
358
  })
361
359
  form = new FormGroup({
362
- mode: ''
360
+ mode: '' // Will be a single string 'dark' or 'light'
363
361
  });
364
362
  ```
365
363
 
@@ -368,9 +366,32 @@ form = new FormGroup({
368
366
  <label> <input name="mode" type="checkbox" value="light" /> Light </label>
369
367
  ```
370
368
 
371
- Checking "Dark" unchecks "Light" automatically.
369
+ ### 3. Per-Field Multi-Select Override
370
+
371
+ You can mix single-select and multi-select groups in the same form by keeping the global `multi: false` (default) and adding the `multiple` attribute to specific inputs.
372
+
373
+ ```typescript
374
+ @Form({
375
+ name: 'mixed-form',
376
+ multi: false // Default (Single Select)
377
+ })
378
+ form = new FormGroup({
379
+ mode: '', // Single value
380
+ tags: [] // Array of values
381
+ });
382
+ ```
383
+
384
+ ```html
385
+ <!-- Single Select (Radio behavior) -->
386
+ <input name="mode" type="checkbox" value="A" />
387
+ <input name="mode" type="checkbox" value="B" />
388
+
389
+ <!-- Multi Select (Array behavior) via 'multiple' attribute -->
390
+ <input name="tags" type="checkbox" value="news" multiple />
391
+ <input name="tags" type="checkbox" value="tech" multiple />
392
+ ```
372
393
 
373
- ### 3. Framework-Agnostic Usage (Vanilla JS)
394
+ ### 4. Framework-Agnostic Usage (Vanilla JS)
374
395
 
375
396
  You can use this library without Decorators or LitHtml, with any UI library or vanilla HTML.
376
397
 
@@ -76,11 +76,12 @@ class FormGroup {
76
76
  }
77
77
  else if (value[0].constructor === String ||
78
78
  value[0].constructor === Number ||
79
- value[0].constructor === Boolean) {
79
+ value[0].constructor === Boolean ||
80
+ value[0].constructor === Array) {
80
81
  this.value[v] = value[0];
81
82
  }
82
83
  else {
83
- throw new Error(`Input value must be of type 'string', 'boolean' or 'number'`);
84
+ throw new Error(`Input value must be of type 'string', 'boolean', 'array' or 'number'`);
84
85
  }
85
86
  }
86
87
  });
@@ -169,12 +170,19 @@ class FormGroup {
169
170
  .querySelectorAll(`input[name="${this.name}"]:checked`)).values(),
170
171
  ];
171
172
  if (hasMultipleBindings > 1) {
172
- if (!self.options.multi && this.type === 'checkbox') {
173
+ if ((self.options.multi || this.hasAttribute('multiple')) &&
174
+ this.type === 'checkbox') {
173
175
  value = inputsWithBindings.map((e) => e.value);
174
176
  }
175
- if (self.options.multi) {
176
- inputsWithBindings.forEach((el) => (el.checked = false));
177
+ if (!self.options.multi &&
178
+ !this.hasAttribute('multiple') &&
179
+ this.type === 'checkbox') {
180
+ inputsWithBindings.forEach((el) => {
181
+ if (el !== this)
182
+ el.checked = false;
183
+ });
177
184
  this.checked = true;
185
+ value = this.value;
178
186
  }
179
187
  }
180
188
  self.resetErrors();
@@ -452,8 +460,12 @@ class FormGroup {
452
460
  // User code had return; but we might want to update model even if no input?
453
461
  // return;
454
462
  }
455
- if (input && input.value !== undefined)
463
+ if (input &&
464
+ input.value !== undefined &&
465
+ input.type !== 'checkbox' &&
466
+ input.type !== 'radio') {
456
467
  input.value = value;
468
+ }
457
469
  const values = this.value;
458
470
  values[name] = value;
459
471
  this.value = values;
@@ -472,7 +484,18 @@ class FormGroup {
472
484
  setInputs(inputs) {
473
485
  this.inputs = new Map(inputs.map((e) => {
474
486
  const key = this.getModelKeyName(e.name);
475
- e.value = this.getValue(key);
487
+ const modelValue = this.getValue(key);
488
+ if (e.type === 'checkbox' || e.type === 'radio') {
489
+ if (Array.isArray(modelValue)) {
490
+ e.checked = modelValue.includes(e.value);
491
+ }
492
+ else {
493
+ e.checked = modelValue === e.value;
494
+ }
495
+ }
496
+ else {
497
+ e.value = modelValue;
498
+ }
476
499
  e.valueChanges = this._valueChanges.pipe((0, operators_1.map)((value) => value === null || value === void 0 ? void 0 : value[key]), (0, operators_1.distinctUntilChanged)());
477
500
  return [key, e];
478
501
  }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rxdi/forms",
3
- "version": "0.7.229",
3
+ "version": "0.7.231",
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.228",
15
+ "@rxdi/lit-html": "^0.7.230",
16
16
  "@types/node": "^25.0.3",
17
17
  "rxjs": "^7.8.2",
18
18
  "typescript": "^5.9.3"