astro-reactive-form/packages/form/components/Field.astro
Ayo Ayco d128747240
feat(validator): server-side rendered validation errors (#123)
* feat(validator): server-side rendered validation errors

* test(form): field should render error

* refactor: remove comment

* fix: incorrect imports

* chore: update deps

* chore: update build commands
2022-10-22 04:35:16 +02:00

98 lines
2.2 KiB
Text

---
import type { FormControl } from '../core/form-control';
export interface Props {
control: FormControl;
showValidationHints: boolean;
showErrors?: boolean;
showOnlyLabel?: boolean;
}
const { control, showValidationHints, showErrors = false, showOnlyLabel = false } = Astro.props;
const { validators = [] } = control;
const isRequired: boolean = showValidationHints && validators.includes('validator-required');
const hasErrors: boolean = showValidationHints && !!control.errors?.length;
const validatorAttributes: Record<string, string> = validators?.reduce(
(prev, validator) => {
const split: string[] = validator.split(':');
const label: string = `data-${split[0]}` || 'invalid';
const value: string | null = split.length > 1 ? split[1] ?? null : 'true';
return {
...prev,
[label]: value,
};
},
{}
);
---
<div
class="field"
data-validator-hints={showValidationHints?.toString()}
data-validator-haserrors={hasErrors ? hasErrors?.toString() : null}
>
{
control.label && control.labelPosition === 'left' && (
<label for={control?.id ?? control.name}>
{isRequired && <span>*</span>}
{control.label}
</label>
)
}
{
!showOnlyLabel && (
<input
name={control.name}
id={control?.id ?? control.name}
type={control.type}
value={control.value?.toString()}
checked={control.value === 'checked'}
placeholder={control.placeholder}
data-label={control.label}
data-label-position={control.labelPosition}
data-validator-haserrors={hasErrors ? hasErrors?.toString() : null}
class:list={[{ 'has-errors': hasErrors }]}
{...validatorAttributes}
/>
)
}
{
showErrors &&
hasErrors &&
control.errors.map((error) => (
<li>
{error.error} {error.limit}
</li>
))
}
{
control.label && control.labelPosition === 'right' && (
<label for={control?.id ?? control.name}>
{isRequired && <span>*</span>}
{control.label}
</label>
)
}
</div>
<style>
/**
TODO: remove usage of data-validator-haserrors,
class has-errors is sufficient
*/
[data-validator-hints='true'][data-validator-haserrors='true'],
[data-validator-hints='true'] [data-validator-haserrors='true'],
.has-errors {
color: red;
border-color: red;
}
</style>