spected icon indicating copy to clipboard operation
spected copied to clipboard

Its possible to tell if the whole structure has been validated without errors?

Open cloud-walker opened this issue 7 years ago • 11 comments

A function like allTheFieldOfTheNestedStructureAreTrue

I need to know if there is at least an error or not, to integrate spected with Formik

The formik hoc validate hook expect an empty object if the form has no errors, so I think to do something like

{
  validate: values => {
    const res = spected(validationSpecs, values)

    return isValid(res) ? ({}) : res
  }
}

cloud-walker avatar Aug 04 '17 13:08 cloud-walker

Should work without too much work!

busypeoples avatar Aug 04 '17 13:08 busypeoples

The isValid has to be implemented in user land, as spected can't know how your data structure looks like. i.e. A successful data structure might look like the following:

{ name: true, nr: true }

or like this i.e.:

{ name: null, nr: null}

This is due to the fact that spected also offers the low level validate function which enables oto define own success and fail callbacks, see also API Docs

Here is an example showing how isValid could be implemented for a regular spected call.

import spected from 'spected'

const data = {
  nr: 6,
  name: 'foobar'
}

const spec = {
  nr: [[ nr => nr > 2, 'Nr has to be greater than 2' ]],
  name: [[ name => name.length > 4, 'Name has to be minimum lenght of 5!' ]]
}

const r1 = spected(spec, data)

const isValid = input => Object.values(input).filter(x => x !== true).length === 0 

// or functional...
// const isValid = R.compose(R.isEmpty, R.filter(x => x !== true), R.values)

console.log(r1, isValid(r1))

Also check the demo: http://jsbin.com/liragopide/edit?js,console,output

Also check the demo using the low level validate: http://jsbin.com/nisuyadecu/1/edit?js,console,output

busypeoples avatar Aug 04 '17 13:08 busypeoples

Yes! I've already tought about that, btw my problem is that my form values structure is nested:

const values = {
  email: '[email protected]',
  posts: [
    {
      title: 'Learn functional programming the right way',
      body: 'lorem',
    },
    {
      title: 'How to become a better developer',
      body: 'lorem',
    },
  ],
}

So reading your source code, I think the best way to do it is an helper (?) that can take advantage of the same validationSpecs used on the normal spected function to return true / false

Like, I'm guessing here:

const values = {...}
const validationSpecs = {...}

isValid(validationSpecs, values) // true or false

The only problem is that I need now to run twice the algorithm, one for isValid and one for the actual validation output... mmmh!

cloud-walker avatar Aug 04 '17 13:08 cloud-walker

Nested shouldn't be a problem either. Check isValid in the revalidation library. It works with nested structures. https://github.com/25th-floor/revalidation/blob/master/src/utils/isValid.js

This is how revalidation calculates the valid state after validating with spected. So I would pass the result returned from calling spected to the isValid function.

revalidation defines the success callback like this:

() => []

https://github.com/25th-floor/revalidation/blob/master/src/validate.js

So you might have to adapt the isValid function to check if true f.e.

busypeoples avatar Aug 04 '17 14:08 busypeoples

If you need any help, let me know. I really like the idea of combing spected with Formik

busypeoples avatar Aug 04 '17 14:08 busypeoples

No I think its ok, the only concern may be performance because I need first to run spected to generate the validation results, and then run a isValid function over it (so re-visiting the structure) over the validation results to determine if there is an error or not.

I continue to suspect that the spected validate function itself should return an errors count or true or false if validation is passed or not, like:

spected(validationSpecs, values)
/*
  The function above returns {
    valid: true | false,
    schema: {
       here the normal validation object of the spected library
    }
  }
  
  or {
    count: 0 or n errors counted during reduce,
    schema: {
       here the normal validation object of the spected library
    }
  }
*/

I can't imagine a better solution but it feels ugly... and also could be a breaking change..

cloud-walker avatar Aug 04 '17 14:08 cloud-walker

Hey, what about something like this:

const specialSpected = (spec, input) => {
  let valid = true;
 
  const failFunc = (f) => {
    if (valid) {
      valid = false;
    }
    
    return f;
  };
  
 
  const validation = validate(() => true, failFunc, spec, input);
  
  return {
    valid,
    validation
  };
}

In this way you have no performance hit because you don't have to traverse the object again. I don't know if a solution like this should be provided by spected itself, I can't think of an elegant way to integrate it in the current API other than providing another function, which sounds like unnecessary complexity.

(demo: http://jsbin.com/coqodotuyo/edit?js,console,output)

daniele-rapagnani avatar Aug 04 '17 16:08 daniele-rapagnani

I've sketched out a possible isValid function, here: http://jsbin.com/seworut/edit?js,output

For @daniele-rapagnani : I don't like to integrate the current idea either, but I still think it should be in the library, as its a common case, and I bet the most of the libraries out there will need it.

Cool trick BTW!

cloud-walker avatar Aug 04 '17 16:08 cloud-walker

@cloud-walker @daniele-rapagnani Thanks for the very valuable input! I would rather avoid making isValid or valid a part of the API. I would rather like to see spected as a part of a pipeline. But I'll keep the issue open, maybe we can come up with a reasonable solution.

busypeoples avatar Aug 04 '17 18:08 busypeoples

Sure! Maybe we can add refined version of the @daniele-rapagnani recipe on the future FAQ?

ref: https://github.com/25th-floor/spected/issues/82

cloud-walker avatar Aug 04 '17 21:08 cloud-walker

Yes, this would be really useful!

busypeoples avatar Aug 05 '17 12:08 busypeoples