Skip to content

Simplified Validation API #1

Description

@mrjackdavis

I propose we improve validation via observables.

  • An operator should be passed in to the form HOC
  • This operator will receive an observable prop which will receive input when a field is requested for validation. It should also receive enough information to make an informed validation decision. Perhaps the form model will do
  • Simultaneously, the form will receive an update which says the field is undergoing validation
  • The operator's returned observable should receive input each time a field is validated. It should not be necessary to return 1:1 validation results for validation requests. There could be many validation results for a single input

At it's core:

|-o---------o------------o------>|
ValidationOperator
|-o------------o---------o---o-->|

Where the first observable input is of type

{
  field:string, // pointer to field
  model:ImmutableJS.Map
}

And returned observable should output

{
  field:string, // pointer to field
  status:'VALID' | 'INVALID',
  message?:string // Required when INVALID
}

Used like so:

const validationOperator = source=>{
  // ...
}
// ...
LocalStateForm(
  // ...
  validationOperator
)(
  // ...
)

Examples

Very simple

(source)=>
source
.map(validate=>{
  const { field, model } = validate;
  const fieldValue = model.get(field)
  if(validate.field === 'name'){
    return {
      field,
      status: fieldValue == true ? 'VALID' : 'INVALID',
      message:'Name is required'
    };
  } else if(validate.field === 'email'){
    return {
      field,
      status: fieldValue.includes('@') ? 'VALID' : 'INVALID',
      message:'Email must contain "@"'
    };
  }
})

ASync validation

Assuming there's a single field username

(source)=>
source
.switchMap(async (validate)=>{
  const { field, model } = validate;
  const fieldValue = model.get(field)
  const usernameAvailable = await IsUsernameAvailable(fieldValue);
  return {
    field,
    status: usernameAvailable ? 'VALID' : 'INVALID',
    message:`Username "${fieldValue}" is invalid`
  }
})

But its complicated

Such a powerful API is difficult to grok.
90% of the time, developers will just want to use a simple function.

(field, value)=>void // Throws error if invalid

This could be achieved very simply with helper functions. i.e.

const validationOperator = simpleValidation((field,value) => {
  switch(field):
    // ...
})
// ...
LocalStateForm(
  // ...
  validationOperator
)(
  // ...
)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions