{"action":"created","issue":{"url":"https://api.github.com/repos/angular/angular/issues/1693","labels_url":"https://api.github.com/repos/angular/angular/issues/1693/labels{/name}","comments_url":"https://api.github.com/repos/angular/angular/issues/1693/comments","events_url":"https://api.github.com/repos/angular/angular/issues/1693/events","html_url":"https://github.com/angular/angular/issues/1693","id":73465303,"number":1693,"title":"Implement element size/position/visibel event","user":{"login":"mhevery","id":111951,"avatar_url":"https://avatars.githubusercontent.com/u/111951?v=3","gravatar_id":"","url":"https://api.github.com/users/mhevery","html_url":"https://github.com/mhevery","followers_url":"https://api.github.com/users/mhevery/followers","following_url":"https://api.github.com/users/mhevery/following{/other_user}","gists_url":"https://api.github.com/users/mhevery/gists{/gist_id}","starred_url":"https://api.github.com/users/mhevery/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mhevery/subscriptions","organizations_url":"https://api.github.com/users/mhevery/orgs","repos_url":"https://api.github.com/users/mhevery/repos","events_url":"https://api.github.com/users/mhevery/events{/privacy}","received_events_url":"https://api.github.com/users/mhevery/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/angular/angular/labels/%E2%99%A5%20GT","name":"♥ GT","color":"e11d21"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-05-05T23:47:27Z","updated_at":"2015-05-06T00:40:55Z","closed_at":null,"body":"## Purpose\r\n\r\nA component should be able to read its size and react to it. This is hard because we have to wait until DOM is fully rendered before causing layout and reading its position. (Additionally the browser does not have a resize event on elements)\r\n\r\n## Mental Model\r\n\r\nA component can register a `size` host event which the framework will call:\r\n\r\n1. On initial render of the component to supply the initial size information.\r\n2. When component size changes.\r\n\r\nComponent may change size due to:\r\n\r\n1. Window resize\r\n2. Changes to DOM rendering (ie text gets longer cause reflow.)\r\n\r\n\r\n## Algorithm\r\n\r\n1. dirty check all host elements which have `size` using `Element.getBoundingClientRect()` at the end of digest cycle when:\r\n  * any DOM rendering occurs (may do pruning if we know that some things are absolutely position, later optimization)\r\n  * a Window resize occurs. (orientation on mobile, which should cause a resize)\r\n2. Invoke `size` handler only if the bounding rectangle has changed.\r\n3. Schedule another `digest` before end of the turn. (This can be done be creating a `Promise` and resolving it within current `digest`.)\r\n\r\n## Notes\r\n\r\n* Other platforms may have this primitives and we don't have to dirty check\r\n* Benefit of having it as event is that we can do proper batching of layouts.\r\n* We can optimize (prune) dirty checking later once we know more about the application structure.\r\n* `Ruler` Service can now be deleted.\r\n* Need to split the `size` event and `position` concern into separate events. \r\n* Events: \r\n  * `size`: when width/height has changed. (Size changes less often then position)\r\n  * `position`: when width/height or position changed.\r\n  * `visible`: when the component is visible on the screen.\r\n\r\n## Example\r\n\r\n```javascript\r\n@Component({\r\n  selector: '...'\r\n})\r\n@View({\r\n  template: `\r\n  <ul style=\"overflow: scroll\" \r\n        (scroll)=\"onScroll($event.target.scrollTop)\"\r\n        (size)=\"onResize($event)\" >\r\n    <li [style.height.px]=\"topPadding\"></li>\r\n    <li *for=\"var row in visibleRows\"></li>\r\n    <li [style.height.px]=\"bottomPadding\"></li>\r\n  </ul>\r\n`\r\n})\r\nclass VirtualScroll {\r\n  visibleRows: Array;\r\n  topPadding: number;\r\n  buttomPadding: number;\r\n\r\n  onScroll(offset: number) {\r\n    // update the visibleRows\r\n  }\r\n\r\n  onResize(rect:Rectangle) {  \r\n    // compute the number of visible rows.\r\n  }\r\n}\r\n```"},"comment":{"url":"https://api.github.com/repos/angular/angular/issues/comments/99275673","html_url":"https://github.com/angular/angular/issues/1693#issuecomment-99275673","issue_url":"https://api.github.com/repos/angular/angular/issues/1693","id":99275673,"user":{"login":"kseamon","id":923677,"avatar_url":"https://avatars.githubusercontent.com/u/923677?v=3","gravatar_id":"","url":"https://api.github.com/users/kseamon","html_url":"https://github.com/kseamon","followers_url":"https://api.github.com/users/kseamon/followers","following_url":"https://api.github.com/users/kseamon/following{/other_user}","gists_url":"https://api.github.com/users/kseamon/gists{/gist_id}","starred_url":"https://api.github.com/users/kseamon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kseamon/subscriptions","organizations_url":"https://api.github.com/users/kseamon/orgs","repos_url":"https://api.github.com/users/kseamon/repos","events_url":"https://api.github.com/users/kseamon/events{/privacy}","received_events_url":"https://api.github.com/users/kseamon/received_events","type":"User","site_admin":false},"created_at":"2015-05-06T00:40:55Z","updated_at":"2015-05-06T00:40:55Z","body":"On the surface, this seems reasonable. I know it's marked for later, but finding out of a dirtied bit of dom i out of flow might be more costly than just triggering the event naively.\r\n\r\nIs it possible to trigger the event and subsequent dirty check synchronously (I assume using a promise makes it asynchronous)? If it's asynchronous, the user may perceive a flicker as the UI readjusts."}}