gcanti / tcomb-form

Forms library for react
https://gcanti.github.io/tcomb-form
MIT License
1.16k stars 136 forks source link

Multi select list not vaildating? #324

Closed awhillas closed 8 years ago

awhillas commented 8 years ago

Version

Tell us which versions you are using:

The multi selects are required and should pull a validation error when submit is called with anything selected.

Actual behaviour

No validation errors are called.

Steps to reproduce

  1. Following the multi-select docs i nested t.emuns inside a t.list like so: t.list(t.enums(tags))
  2. submit without selecting anything. no errors.
  3. Dropping the t.list and just using 't.enums(tags)', validation starts to work.

The source code for this is a little complex as the structure is being dynamically generated from JSON:

taxonomys: [{
    'id': 22,
    'name': 'Genre',
    'tag_set': [{
        'id': 124,
        'name': 'tag1'
    }, {
        'id': 135,
        'name': 'tag12'
    },
       // ...
]}, {
    'id': 23,
    'name': 'Instruments',
    'tag_set': [{
        'id': 136,
        'name': 'tag13'
    }, {
        'id': 140,
        'name': 'tag17'
    }]
}]

with this code:

  getTaxonomyForms() {
    // Build set of taxonomys multi-select list inputs
    let subForms = {};
    let opts = {fields:{}};
    taxonomys.forEach((tax) => {
      let tags = {};
      tax.tag_set.forEach((tag) => { tags[tag.id] = tag.name })
      subForms[tax.name] = t.list(t.enums(tags));  // THE LINE IN QUESTION
//      subForms[tax.name] = t.enums(tags);  // when changed to this validation starts to work again?
      opts.fields[tax.name] = { factory: t.form.Select };
    });
    return {
      taxonomyForm: t.struct(subForms),
      tagsOptions: opts
    };
  }

this get stuffed into t.Struct as a subform:

    let {taxonomyForm, tagsOptions} = this.getTaxonomyForms();

    let type = t.struct({
      title: t.String,
      variation_set: Variation,
      tags: taxonomyForm
    });

Am i building the subform correctly. It should look something like this:

t.Struct({
  Genre: t.list(t.enums(tags)),
  Instruments: t.list(t.enums(tags))
})

where tags = {124: 'tag1', 135: 'tag12'} and with options like this:

var options = {
  fields: {
    Genre: { factory: t.form.Select },
    Instruments: { factory: t.form.Select }
  }
}

?

gcanti commented 8 years ago

In general it's acceptable an empty list, so there's no error (by design). You can specify how many selections are required using a refinement:

const Car = t.enums.of('Audi Chrysler Ford Renault Peugeot')

const atLeastOne = arr => arr.length > 0

const Type = t.struct({
  car: t.refinement(t.list(Car), atLeastOne)
})

const options = {
  fields: {
    car: {
      factory: t.form.Select
    }
  }
}
awhillas commented 8 years ago

Ah cool, thanks! I thought unless a field is wrapped in an t.maybe then it was required. Again, my bad.