{"action":"created","issue":{"url":"https://api.github.com/repos/angular/angular/issues/1800","labels_url":"https://api.github.com/repos/angular/angular/issues/1800/labels{/name}","comments_url":"https://api.github.com/repos/angular/angular/issues/1800/comments","events_url":"https://api.github.com/repos/angular/angular/issues/1800/events","html_url":"https://github.com/angular/angular/issues/1800","id":75043631,"number":1800,"title":"Streamline directive definitions with more liberal use of decorators","user":{"login":"ewinslow","id":356564,"avatar_url":"https://avatars.githubusercontent.com/u/356564?v=3","gravatar_id":"","url":"https://api.github.com/users/ewinslow","html_url":"https://github.com/ewinslow","followers_url":"https://api.github.com/users/ewinslow/followers","following_url":"https://api.github.com/users/ewinslow/following{/other_user}","gists_url":"https://api.github.com/users/ewinslow/gists{/gist_id}","starred_url":"https://api.github.com/users/ewinslow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ewinslow/subscriptions","organizations_url":"https://api.github.com/users/ewinslow/orgs","repos_url":"https://api.github.com/users/ewinslow/repos","events_url":"https://api.github.com/users/ewinslow/events{/privacy}","received_events_url":"https://api.github.com/users/ewinslow/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/angular/angular/labels/comp:%20core/view/compiler","name":"comp: core/view/compiler","color":"c7def8"},{"url":"https://api.github.com/repos/angular/angular/labels/effort3:%20hard%20(week)","name":"effort3: hard (week)","color":"bfe5bf"},{"url":"https://api.github.com/repos/angular/angular/labels/P4:%20nice%20to%20have","name":"P4: nice to have","color":"fef2c0"},{"url":"https://api.github.com/repos/angular/angular/labels/state:%20Needs%20Design","name":"state: Needs Design","color":"006b75"},{"url":"https://api.github.com/repos/angular/angular/labels/type:%20feature","name":"type: feature","color":"EEEEEE"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":9,"created_at":"2015-05-11T01:16:29Z","updated_at":"2015-08-02T11:17:32Z","closed_at":null,"body":"According to the docs, making a directive that listens for events on the host element is like so:\r\n\r\n```ts\r\n@Directive({\r\n  selector: 'input',\r\n  hostListeners: {\r\n    'change': 'onChange($event)',\r\n    'window:resize': 'onResize($event)'\r\n  }\r\n})\r\nclass InputDirective {\r\n  onChange(event:Event) {}\r\n  onResize(event:Event) {}\r\n}\r\n```\r\n\r\nThis seems like it could be streamlined:\r\n\r\n * The listeners are registered far away from where the handlers are defined\r\n * The registration duplicates a) the method names and b) arguments.\r\n * The registration uses strings which makes obfuscation and refactoring more difficult.\r\n * You can listen for global events, too (seems odd that the **host**Listener object lets you do this)\r\n * Listening for global events depends on a magic string prefix of \"window:\" (or \"document:\" or \"body:\", implied by the docs)\r\n\r\nHere's a possible alternative:\r\n\r\n```ts\r\n@Directive({\r\n  selector: 'input'\r\n})\r\nclass InputDirective {\r\n  @HostListener('change')\r\n  onChange(event: Event) {}\r\n  \r\n  @WindowListener('resize')\r\n  onResize(event: Event) {}\r\n}\r\n```\r\n\r\nThis doesn't suffer from any of the problems listed above.\r\n\r\nYou can imagine a similar streamlining for properties. Currently you write:\r\n\r\n```ts\r\n@Directive({\r\n  selector: '[dependency]',\r\n  properties: {\r\n    'id':'dependency'\r\n  }\r\n})\r\nclass Dependency {\r\n  id:string;\r\n}\r\n```\r\n\r\nBut using decorators you could write:\r\n\r\n```ts\r\n@Directive({\r\n  selector: '[dependency]',\r\n})\r\nclass Dependency {\r\n  @Property('dependency')\r\n  id:string;\r\n}\r\n```\r\n\r\nI find it a whole lot easier to understand this, not needing to remember constantly what the left and right hand side of the configuration means. E.g. for `{ 'id': 'dependency' }` I cannot tell easily which one of 'id' or 'dependency' is the JS class property and which is the DOM element property. I constantly get this confused in Angular 1, too, with the scope config. Hopefully we can eliminate this rough edge in Angular 2..."},"comment":{"url":"https://api.github.com/repos/angular/angular/issues/comments/127016630","html_url":"https://github.com/angular/angular/issues/1800#issuecomment-127016630","issue_url":"https://api.github.com/repos/angular/angular/issues/1800","id":127016630,"user":{"login":"dsebastien","id":89887,"avatar_url":"https://avatars.githubusercontent.com/u/89887?v=3","gravatar_id":"","url":"https://api.github.com/users/dsebastien","html_url":"https://github.com/dsebastien","followers_url":"https://api.github.com/users/dsebastien/followers","following_url":"https://api.github.com/users/dsebastien/following{/other_user}","gists_url":"https://api.github.com/users/dsebastien/gists{/gist_id}","starred_url":"https://api.github.com/users/dsebastien/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dsebastien/subscriptions","organizations_url":"https://api.github.com/users/dsebastien/orgs","repos_url":"https://api.github.com/users/dsebastien/repos","events_url":"https://api.github.com/users/dsebastien/events{/privacy}","received_events_url":"https://api.github.com/users/dsebastien/received_events","type":"User","site_admin":false},"created_at":"2015-08-02T11:17:32Z","updated_at":"2015-08-02T11:17:32Z","body":"+1 for @Event() & @Property(); feels natural/explicit/intuitive"}}