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:
Alexander Samaniego 2022-11-08 02:53:22 -05:00 committed by GitHub
parent d02c1e4081
commit 93a8d49f0a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 41 additions and 9 deletions

17
package-lock.json generated
View file

@ -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",

View file

@ -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"
}
}

View file

@ -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) => (

View file

@ -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()}
>
{

View file

@ -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>
)

View file

@ -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}
>
{

View file

@ -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'}

View file

@ -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}

View file

@ -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}

View file

@ -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;
}

View file

@ -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));