feat(form): implement unique IDs (#182)
* Added Short Unique ID npm library * Added unique ID to form-control * Added unique ID to form-group * Unique ID added to <form> * Added unique IDs to control components * Added IDs to label and fieldset * Update Form.astro with requested changes Co-authored-by: Ayo Ayco <ayo@ayco.io> * Adjustments for requested changes. Co-authored-by: Ayo Ayco <ayo@ayco.io>
This commit is contained in:
parent
d02c1e4081
commit
93a8d49f0a
11 changed files with 41 additions and 9 deletions
17
package-lock.json
generated
17
package-lock.json
generated
|
@ -17,7 +17,8 @@
|
|||
"packages/common"
|
||||
],
|
||||
"dependencies": {
|
||||
"prettier-plugin-astro": "^0.7.0"
|
||||
"prettier-plugin-astro": "^0.7.0",
|
||||
"short-unique-id": "^4.4.4"
|
||||
}
|
||||
},
|
||||
"apps/demo": {
|
||||
|
@ -7578,6 +7579,15 @@
|
|||
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
|
||||
"integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w=="
|
||||
},
|
||||
"node_modules/short-unique-id": {
|
||||
"version": "4.4.4",
|
||||
"resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-4.4.4.tgz",
|
||||
"integrity": "sha512-oLF1NCmtbiTWl2SqdXZQbo5KM1b7axdp0RgQLq8qCBBLoq+o3A5wmLrNM6bZIh54/a8BJ3l69kTXuxwZ+XCYuw==",
|
||||
"bin": {
|
||||
"short-unique-id": "bin/short-unique-id",
|
||||
"suid": "bin/short-unique-id"
|
||||
}
|
||||
},
|
||||
"node_modules/signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
|
@ -14421,6 +14431,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"short-unique-id": {
|
||||
"version": "4.4.4",
|
||||
"resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-4.4.4.tgz",
|
||||
"integrity": "sha512-oLF1NCmtbiTWl2SqdXZQbo5KM1b7axdp0RgQLq8qCBBLoq+o3A5wmLrNM6bZIh54/a8BJ3l69kTXuxwZ+XCYuw=="
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
"packages/common"
|
||||
],
|
||||
"dependencies": {
|
||||
"prettier-plugin-astro": "^0.7.0"
|
||||
"prettier-plugin-astro": "^0.7.0",
|
||||
"short-unique-id": "^4.4.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ export interface Props {
|
|||
const { group, showValidationHints, readOnly = false } = Astro.props;
|
||||
---
|
||||
|
||||
<fieldset id={group.name} name={group.name}>
|
||||
<fieldset id={group.id} name={group.name}>
|
||||
{group.name && <legend>{group.name}</legend>}
|
||||
{
|
||||
group?.controls?.map((control) => (
|
||||
|
|
|
@ -3,6 +3,7 @@ import type { Submit } from '@astro-reactive/common';
|
|||
import { FormGroup, FormControl } from '../core';
|
||||
import FieldSet from './FieldSet.astro';
|
||||
import Field from './Field.astro';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
|
||||
export interface Props {
|
||||
formGroups: FormGroup | FormGroup[];
|
||||
|
@ -20,14 +21,16 @@ const {
|
|||
readOnly = false,
|
||||
} = Astro.props;
|
||||
|
||||
const uid = new ShortUniqueId({ length: 9 });
|
||||
const formTheme = theme ?? 'light';
|
||||
const formName = Array.isArray(formGroups) ? null : formGroups?.name || null;
|
||||
const formId = Array.isArray(formGroups) ? uid() : formGroups?.id || null;
|
||||
---
|
||||
|
||||
<form
|
||||
class={formTheme}
|
||||
name={formName}
|
||||
id={formName}
|
||||
id={formId}
|
||||
data-validator-hints={showValidationHints.toString()}
|
||||
>
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@ const isRequired: boolean = showValidationHints && validators.includes('validato
|
|||
|
||||
{
|
||||
control.label && control.type !== "checkbox" && (
|
||||
<label for={control.name} data-validation-required={isRequired ? "true" : null}>
|
||||
<label for={control.id} data-validation-required={isRequired ? "true" : null}>
|
||||
{control.label}
|
||||
</label>
|
||||
)
|
||||
|
@ -26,7 +26,7 @@ const isRequired: boolean = showValidationHints && validators.includes('validato
|
|||
|
||||
{
|
||||
control.label && control.type === "checkbox" && (
|
||||
<label for={control.name} data-validation-required={isRequired ? "true" : null}>
|
||||
<label for={control.id} data-validation-required={isRequired ? "true" : null}>
|
||||
{control.label}
|
||||
</label>
|
||||
)
|
||||
|
|
|
@ -24,7 +24,7 @@ const options = control.options.map((option: string | ControlOption) => {
|
|||
|
||||
<select
|
||||
name={control.name}
|
||||
id={control.name}
|
||||
id={control.id}
|
||||
disabled={readOnly || null}
|
||||
>
|
||||
{
|
||||
|
|
|
@ -30,7 +30,7 @@ const validatorAttributes: Record<string, string> = validators?.reduce((prev, va
|
|||
|
||||
<input
|
||||
name={control.name}
|
||||
id={control.name}
|
||||
id={control.id}
|
||||
type={control.type as InputType}
|
||||
value={control.value?.toString()}
|
||||
checked={control.value === 'checked'}
|
||||
|
|
|
@ -27,6 +27,7 @@ const options = control.options.map((option: string | ControlOption) => {
|
|||
<div class="radio-option">
|
||||
<input
|
||||
type="radio"
|
||||
id={control.id}
|
||||
name={control.name}
|
||||
value={option.value}
|
||||
checked={option.value === control.value}
|
||||
|
|
|
@ -27,7 +27,7 @@ const validatorAttributes: Record<string, string> = validators?.reduce((prev, va
|
|||
|
||||
<textarea
|
||||
name={control.name}
|
||||
id={control.name}
|
||||
id={control.id}
|
||||
placeholder={control?.placeholder}
|
||||
rows={control?.rows ?? 3}
|
||||
cols={control?.cols ?? 21}
|
||||
|
|
|
@ -10,10 +10,12 @@ import type {
|
|||
TextArea,
|
||||
ControlBase,
|
||||
} from '@astro-reactive/common';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
|
||||
export type ControlConfig = ControlBase | Checkbox | Radio | Submit | Button | Dropdown | TextArea;
|
||||
|
||||
export class FormControl {
|
||||
private _id = '';
|
||||
private _name = '';
|
||||
private _type: ControlType = 'text';
|
||||
private _value?: string | number | null | string[] | ControlOption[];
|
||||
|
@ -46,6 +48,8 @@ export class FormControl {
|
|||
validators = [],
|
||||
} = config;
|
||||
|
||||
const uid = new ShortUniqueId({ length: 9 });
|
||||
this._id = 'arl-' + uid();
|
||||
this._name = name;
|
||||
this._type = type;
|
||||
this._value = value;
|
||||
|
@ -80,6 +84,10 @@ export class FormControl {
|
|||
});
|
||||
}
|
||||
|
||||
get id() {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import { ControlConfig, FormControl } from './form-control';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
|
||||
export class FormGroup {
|
||||
controls: FormControl[];
|
||||
name?: string;
|
||||
id?: string;
|
||||
|
||||
constructor(controls: ControlConfig[], name = '') {
|
||||
const uid = new ShortUniqueId({ length: 9 });
|
||||
this.name = name;
|
||||
this.id = 'arl-' + uid();
|
||||
this.controls = controls
|
||||
.filter((control) => control.type !== 'submit')
|
||||
.map((control) => new FormControl(control));
|
||||
|
|
Loading…
Reference in a new issue