{"action":"created","issue":{"url":"https://api.github.com/repos/gcanti/tcomb-form/issues/327","repository_url":"https://api.github.com/repos/gcanti/tcomb-form","labels_url":"https://api.github.com/repos/gcanti/tcomb-form/issues/327/labels{/name}","comments_url":"https://api.github.com/repos/gcanti/tcomb-form/issues/327/comments","events_url":"https://api.github.com/repos/gcanti/tcomb-form/issues/327/events","html_url":"https://github.com/gcanti/tcomb-form/pull/327","id":154904558,"number":327,"title":"add support for matching union options","user":{"login":"minedeljkovic","id":1811622,"avatar_url":"https://avatars.githubusercontent.com/u/1811622?v=3","gravatar_id":"","url":"https://api.github.com/users/minedeljkovic","html_url":"https://github.com/minedeljkovic","followers_url":"https://api.github.com/users/minedeljkovic/followers","following_url":"https://api.github.com/users/minedeljkovic/following{/other_user}","gists_url":"https://api.github.com/users/minedeljkovic/gists{/gist_id}","starred_url":"https://api.github.com/users/minedeljkovic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/minedeljkovic/subscriptions","organizations_url":"https://api.github.com/users/minedeljkovic/orgs","repos_url":"https://api.github.com/users/minedeljkovic/repos","events_url":"https://api.github.com/users/minedeljkovic/events{/privacy}","received_events_url":"https://api.github.com/users/minedeljkovic/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2016-05-15T11:50:23Z","updated_at":"2016-05-16T13:21:31Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/gcanti/tcomb-form/pulls/327","html_url":"https://github.com/gcanti/tcomb-form/pull/327","diff_url":"https://github.com/gcanti/tcomb-form/pull/327.diff","patch_url":"https://github.com/gcanti/tcomb-form/pull/327.patch"},"body":"This adds support to define options which would vary among concrete types in union.\r\nFor example:\r\n```js\r\nconst options = {\r\n  item: {\r\n    case: {\r\n      KnownAccount: { template: knownAccountTemplate },\r\n      UnknownAccount: { template: unknownAccountTemplate }\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nThis is basically shorthand to write custom:\r\n```js\r\nconst options = {\r\n  item: (value) => {\r\n    const concreteAccountType = Account.dispatch(value);\r\n    switch (concreteAccountType.meta.name) {\r\n      case 'KnownAccount': {\r\n        return { template: knownAccountTemplate }\r\n      }\r\n      case 'UnknownAccount': {\r\n        return { template: knownAccountTemplate }\r\n      }\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nIf you approve this, I could write tests and additional documentation.\r\n\r\nPlease note, that this causes some unneeded renders of some of item (or props in case of Struct) components, because it will create new instance of item options object even if value didn't change. But this is the case as when options function is used (e.g. in my second example), so I think this PR does not add to this issue. Maybe some kind of memoization technique could solve both problems."},"comment":{"url":"https://api.github.com/repos/gcanti/tcomb-form/issues/comments/219423086","html_url":"https://github.com/gcanti/tcomb-form/pull/327#issuecomment-219423086","issue_url":"https://api.github.com/repos/gcanti/tcomb-form/issues/327","id":219423086,"user":{"login":"minedeljkovic","id":1811622,"avatar_url":"https://avatars.githubusercontent.com/u/1811622?v=3","gravatar_id":"","url":"https://api.github.com/users/minedeljkovic","html_url":"https://github.com/minedeljkovic","followers_url":"https://api.github.com/users/minedeljkovic/followers","following_url":"https://api.github.com/users/minedeljkovic/following{/other_user}","gists_url":"https://api.github.com/users/minedeljkovic/gists{/gist_id}","starred_url":"https://api.github.com/users/minedeljkovic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/minedeljkovic/subscriptions","organizations_url":"https://api.github.com/users/minedeljkovic/orgs","repos_url":"https://api.github.com/users/minedeljkovic/repos","events_url":"https://api.github.com/users/minedeljkovic/events{/privacy}","received_events_url":"https://api.github.com/users/minedeljkovic/received_events","type":"User","site_admin":false},"created_at":"2016-05-16T13:21:31Z","updated_at":"2016-05-16T13:21:31Z","body":"> In general seems unlikely to share many options (maybe just the label?):\r\n\r\nI cannot say in general. Take for example `UnknownAccount` | `KnownAccount` example, where they share multiple fields, and you need to configure label for each of them. This would be shared options:\r\n```js\r\n{\r\n  fields: {\r\n    field1: {\r\n      label: 'Label 1'\r\n    },\r\n    field2: {\r\n      label: 'Label 1'\r\n    }\r\n    // field3, field4... all other shared fields\r\n  }\r\n}\r\n```\r\n\r\n>\r\n```js\r\nconst options = {\r\n  label: 'Awesome account' // <= a common label can be here instead\r\n  item: [\r\n    null,\r\n    {\r\n      template: unknownAccountTemplate\r\n    }\r\n  ]\r\n}\r\n```\r\n\r\nI think this is not the same. Here label would be option of list as a whole, not of list item.\r\n\r\nMy second proposal was actually inspired by [tcomb's match function](https://github.com/gcanti/tcomb/blob/master/docs/API.md#pattern-matching-the-match-function). :) It is also some kind of pattern matching (limited to union types). I agree it is less easy to explain, but I beleive it has advantage of not having positional dependency. Plus it resolves shared options problem.\r\n\r\nI beleive it would also support complicated use case:\r\n```js\r\nconst U1 = t.union([A, B])\r\nconst FormType = t.union([C, D, U1])\r\n\r\nconst options = {\r\n  item: {\r\n    case: [\r\n      C, { ... },            // static options\r\n      D, (value) => { ... }, // dynamic options\r\n      U1, {\r\n        case: [                   // sub union\r\n          A, { ... },\r\n          B, { ... }\r\n        ]\r\n      }\r\n    ]\r\n  }\r\n}\r\n```"}}