{"action":"created","issue":{"url":"https://api.github.com/repos/fponticelli/doom/issues/7","labels_url":"https://api.github.com/repos/fponticelli/doom/issues/7/labels{/name}","comments_url":"https://api.github.com/repos/fponticelli/doom/issues/7/comments","events_url":"https://api.github.com/repos/fponticelli/doom/issues/7/events","html_url":"https://github.com/fponticelli/doom/issues/7","id":125006986,"number":7,"title":"AutoComponent idea","user":{"login":"andywhite37","id":274734,"avatar_url":"https://avatars.githubusercontent.com/u/274734?v=3","gravatar_id":"","url":"https://api.github.com/users/andywhite37","html_url":"https://github.com/andywhite37","followers_url":"https://api.github.com/users/andywhite37/followers","following_url":"https://api.github.com/users/andywhite37/following{/other_user}","gists_url":"https://api.github.com/users/andywhite37/gists{/gist_id}","starred_url":"https://api.github.com/users/andywhite37/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/andywhite37/subscriptions","organizations_url":"https://api.github.com/users/andywhite37/orgs","repos_url":"https://api.github.com/users/andywhite37/repos","events_url":"https://api.github.com/users/andywhite37/events{/privacy}","received_events_url":"https://api.github.com/users/andywhite37/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2016-01-05T17:00:38Z","updated_at":"2016-01-05T20:34:22Z","closed_at":null,"body":"This issue is to try to figure out how an `AutoComponent` macro thing could work in doom.  I have some code in a branch to start this, so I can work on it and do a PR.\r\n\r\nThere would be an `doom.AutoComponent` interface with an `@:autoBuild` metadata to transform the implementing class, add the State and Api typedefs, generate getters for state/api properties, setup defaults, etc.\r\n\r\nThe idea is to turn something like this:\r\n\r\n```haxe\r\nenum MyComponentStyle {\r\n  Default;\r\n  Primary;\r\n  Other;\r\n}\r\n\r\n// could have @:noChildren metadata on the class to indicate that the component can't have children?\r\nclass MyComponent implements AutoComponent {\r\n  @:state\r\n  public var style : MyComponentStyle;\r\n\r\n  @:state\r\n  @:optional\r\n  @:default(123)\r\n  public var size : Int;\r\n\r\n  @:api\r\n  public var click : Void -> Void; // should this be an empty function rather than var? - I made it a var, so a property accessor could return api.click\r\n\r\n  @:api\r\n  @:optional\r\n  public var hover : Void -> Void; // should this be an empty function?\r\n\r\n  // user defined render function\r\n  public override function render() : Node {\r\n    var styleClass = switch style { /* some code */ };\r\n    var sizeClass = /* some code */;\r\n\r\n    return div([\r\n      'class' => 'my-component $styleClass $sizeClass',\r\n      'click' => click,\r\n      'hover' => hover\r\n    ], children);\r\n  }\r\n}\r\n```\r\n\r\ninto this (via macros):\r\n\r\n```haxe\r\nenum MyComponentStyle {\r\n  Default;\r\n  Primary;\r\n  Other;\r\n}\r\n\r\ntypedef MyComponentApi = {\r\n  public function click() : Void;\r\n  public function hover() : Void;\r\n}\r\n\r\ntypedef MyComponentState = {\r\n  style : MyComponentStyle,\r\n  size : Int\r\n}\r\n\r\nclass MyComponent extends Component<MyComponentApi, MyComponentState> {\r\n  public var style(get, null) : MyComponentStyle;\r\n  public var size(get, null) : Int;\r\n  public var click(get, null) : Void -> Void;\r\n  public var hover(get, null) : Void -> Void;\r\n\r\n  // don't generate ctor - use super ctor\r\n\r\n  // static convenience constructor function\r\n  // should this call `render` on the component and return Node?\r\n  public static function create(click : Void -> Void, ?optApi : { ?hover: Void -> Void }, style : MyComponentStyle, ?optState : { ?size : Int }, ?children : Nodes) : MyComponent {\r\n    if (optApi == null) optApi = {};\r\n    if (optApi.hover == null) optApi.hover = function() {}; // no-op - not sure how best to deal with this\r\n    if (optState == null) optState = {};\r\n    if (optState.size == null) optState.size = 123; // from @:default metadata\r\n    return new MyComponent({\r\n      click: click,\r\n      hover: optApi.hover\r\n    }, {\r\n      style: style,\r\n      size: optState.size\r\n    }, children);\r\n  }\r\n\r\n  public override function render() : Node {\r\n    // unchanged from above\r\n  }\r\n\r\n  public function get_style() : MyComponentStyle {\r\n    return state.style;\r\n  }\r\n\r\n  public function get_size() : Int {\r\n    return state.size;\r\n  }\r\n\r\n  public function get_click() : Void -> Void {\r\n    return api.click;\r\n  }\r\n\r\n  public function get_hover() : Void -> Void {\r\n    return api.hover;\r\n  }\r\n\r\n  // all other functions from above preserved here\r\n}\r\n```\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/fponticelli/doom/issues/comments/169125076","html_url":"https://github.com/fponticelli/doom/issues/7#issuecomment-169125076","issue_url":"https://api.github.com/repos/fponticelli/doom/issues/7","id":169125076,"user":{"login":"andypellucid","id":8048750,"avatar_url":"https://avatars.githubusercontent.com/u/8048750?v=3","gravatar_id":"","url":"https://api.github.com/users/andypellucid","html_url":"https://github.com/andypellucid","followers_url":"https://api.github.com/users/andypellucid/followers","following_url":"https://api.github.com/users/andypellucid/following{/other_user}","gists_url":"https://api.github.com/users/andypellucid/gists{/gist_id}","starred_url":"https://api.github.com/users/andypellucid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/andypellucid/subscriptions","organizations_url":"https://api.github.com/users/andypellucid/orgs","repos_url":"https://api.github.com/users/andypellucid/repos","events_url":"https://api.github.com/users/andypellucid/events{/privacy}","received_events_url":"https://api.github.com/users/andypellucid/received_events","type":"User","site_admin":false},"created_at":"2016-01-05T20:34:22Z","updated_at":"2016-01-05T20:34:22Z","body":"For point #5 about implementing a constructor and setting the fields on the component instance - that makes sense, but then is there any reason to have the \"state\" object/type on the Component?"}}