Skip to content

Simplified Validation API #1

@mrjackdavis

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions