{"action":"created","issue":{"url":"https://api.github.com/repos/erikras/redux-form/issues/98","labels_url":"https://api.github.com/repos/erikras/redux-form/issues/98/labels{/name}","comments_url":"https://api.github.com/repos/erikras/redux-form/issues/98/comments","events_url":"https://api.github.com/repos/erikras/redux-form/issues/98/events","html_url":"https://github.com/erikras/redux-form/issues/98","id":108500974,"number":98,"title":"Allow for composable/declarative validation (enhancement)","user":{"login":"davidkpiano","id":1093738,"avatar_url":"https://avatars.githubusercontent.com/u/1093738?v=3","gravatar_id":"","url":"https://api.github.com/users/davidkpiano","html_url":"https://github.com/davidkpiano","followers_url":"https://api.github.com/users/davidkpiano/followers","following_url":"https://api.github.com/users/davidkpiano/following{/other_user}","gists_url":"https://api.github.com/users/davidkpiano/gists{/gist_id}","starred_url":"https://api.github.com/users/davidkpiano/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davidkpiano/subscriptions","organizations_url":"https://api.github.com/users/davidkpiano/orgs","repos_url":"https://api.github.com/users/davidkpiano/repos","events_url":"https://api.github.com/users/davidkpiano/events{/privacy}","received_events_url":"https://api.github.com/users/davidkpiano/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-09-26T22:52:55Z","updated_at":"2015-09-27T10:00:43Z","closed_at":null,"body":"An idea that I would really like to see for Redux-Form is declaratively defining validation for each field in a form, much in the same spirit as [combineReducers](http://rackt.github.io/redux/docs/api/combineReducers.html) in Redux:\r\n\r\n```js\r\n// Example with synchronous validation\r\n\r\nContactForm = connectReduxForm({\r\n  form: 'contact',\r\n  fields: ['name', 'address', 'phone'],\r\n  validate: {\r\n    name: [\r\n      (field) => field.touched && !field.value && 'Required'\r\n    ],\r\n    address: [\r\n      (field) => !field.value && 'Required',\r\n      (field) => field.touched && field.value && field.value.length > 50\r\n        && 'Must be fewer than 50 characters'\r\n    ],\r\n    phone: [\r\n      (field) => field.touched && !/\\d{3}-\\d{3}-\\d{4}/.test(field.value)\r\n        && 'Phone must match the form \"999-999-9999\"',\r\n      (field, fields) => !fields.fax.value && !field.value && 'Must specify either a phone or fax number'\r\n    ],\r\n    fax: [\r\n      // etc.\r\n    ]\r\n  }\r\n})(ContactForm);\r\n```\r\n\r\nThe benefits for this are:\r\n- It's declarative; makes it trivial to dynamically add/modify, reference, and share validation\r\n- Can define multiple validation rules per field, which permits _multiple_ validation messages per field\r\n- Both `field` and `form` are passed into each validation function for each field, so validation can be contextual (e.g., based on other fields, such as how `fields.phone` is based on `fields.fax`).\r\n- Validation is aware of the entire `field` object; so verbose validation conditionals such as `{address.error && address.touched && <div>{address.error}</div>}` are reduced to `<div>{address.error}</div>`.\r\n- The final validation object is _actually_ immutable all the way through, instead of constantly and manually mutating an `errors = {}` object. :wink: \r\n\r\nWhat do you think? I'd be more than happy to submit a pull request if you like this idea/design."},"comment":{"url":"https://api.github.com/repos/erikras/redux-form/issues/comments/143534271","html_url":"https://github.com/erikras/redux-form/issues/98#issuecomment-143534271","issue_url":"https://api.github.com/repos/erikras/redux-form/issues/98","id":143534271,"user":{"login":"erikras","id":4396759,"avatar_url":"https://avatars.githubusercontent.com/u/4396759?v=3","gravatar_id":"","url":"https://api.github.com/users/erikras","html_url":"https://github.com/erikras","followers_url":"https://api.github.com/users/erikras/followers","following_url":"https://api.github.com/users/erikras/following{/other_user}","gists_url":"https://api.github.com/users/erikras/gists{/gist_id}","starred_url":"https://api.github.com/users/erikras/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/erikras/subscriptions","organizations_url":"https://api.github.com/users/erikras/orgs","repos_url":"https://api.github.com/users/erikras/repos","events_url":"https://api.github.com/users/erikras/events{/privacy}","received_events_url":"https://api.github.com/users/erikras/received_events","type":"User","site_admin":false},"created_at":"2015-09-27T10:00:43Z","updated_at":"2015-09-27T10:00:43Z","body":"This is very similar to my initial instincts when writing a validation function. [Like this](https://github.com/erikras/react-redux-universal-hot-example/blob/35dda221a48b4602fc3cd746d1c4474c0831cb29/src/components/WidgetForm/widgetValidation.js), which calls [this](https://github.com/erikras/react-redux-universal-hot-example/blob/35dda221a48b4602fc3cd746d1c4474c0831cb29/src/utils/validation.js).\r\n\r\nYour idea has some merit. The holes I'm about to poke in it might not be enough to sink it. I'm not convinced that redux-form enforcing this opinionated design is superior to just requiring a function, which could be adapted to any number of existing validation libraries.\r\n\r\nSome problems I see with your idea:\r\n* You can no longer use the same validation function on the client and the server if your validation function is concerned with field state.\r\n* It's a mix of concerns that are presently neatly separated, namely validation and error display.\r\n* The reduction of `{address.error && address.touched && <div>{address.error}</div>}` that you state as a benefit could be handled by the simplest `<Error field={address}/>` component very nicely.\r\n* The immutability of the `errors` object is up to how clever you want to be with your validation function. It has nothing to do with the library. The one in the README example was intentionally simplistic.\r\n\r\nI could certainly entertain the idea of allowing `fields` to be passed, as a second parameter (to let the same function work on the server) to the `validate` function."}}