open-scd icon indicating copy to clipboard operation
open-scd copied to clipboard

Form library

Open clepski opened this issue 8 months ago • 1 comments

As a developer I would like to have a way of quickly creating forms out of a set of input like textfield, checkbox, number input etc. I want to be able to add validators for each form field like required or pattern for a textfield and have the form validate on submit and show errors on its own.

Requirements

  • Add wrapper for inputs like textfield, checkbox (what inputs do we need?)
  • Implement a handler that can use validator functions on an input and display a custom error message.
  • Add common default validators like required, pattern etc
  • Trigger validation on form submit

clepski avatar Jun 25 '25 13:06 clepski

Sketch on how an implementation could look like


type Value = null | string | number | boolean;

// Interface to be usable with material form fields such as MdTextField, MdSelect etc
interface FormField {
  value: Value | Value[];
  validate: () => boolean;
  error: boolean;
  errorText: string | null;
}

const dummyField: FormField = {
  value: null,
  validate: () => true,
  error: false,
  errorText: null
}

// Return null for a valid field and an error text to display for an validation error
interface Validator {
  (fieldValue: Value, formValue: { [key: string]: Value }): null | string;
}

interface FormFieldDefinition {
  formField: FormField,
  validators?: Validator | Validator[]
}


class FormGroup {
  constructor(form: { [key: string]: FormFieldDefinition }) {
  }

  validate(): boolean {
    // Iterate each form field and run its own validate method and every Validator
    // Set error and errorText on the form field if necessary

    return true;
  };

  reset(): void {
    // Reset error and errorText state on all form fields
  }
}

// Have build in Validators for the most common use cases
const Validators = {
  Required: (errorMessage: string) => () => errorMessage
}

// ------- Example usage ------- 

// Form fields are references to MdFormField components
const nameField: FormField = dummyField;
const isActiveField: FormField = dummyField;
const ageField: FormField = dummyField;

// Example for custom validator
const isOver18Validator: Validator = (fieldValue, formValue) => {
  if (!fieldValue || typeof fieldValue !== 'number') {
    return null;
  }

  const isValid = fieldValue >= 18

  return isValid ? null : 'Age must be 18 or higher';
}

// Define the form group once with appropriate validators attached
const formGroup = new FormGroup({
  name: {
    formField: nameField,
    validators: Validators.Required('Name is required')
  },
  age: {
    formField: ageField,
    validators: isOver18Validator
  },
  isActive: {
    formField: isActiveField
  }
})

// The form validation should be very easy and short to use
const saveChanges = () => {
  if (!formGroup.validate()) {
    return;
  }

  // Save changes etc
}



clepski avatar Aug 06 '25 13:08 clepski