payload: {"action":"created","issue":{"url":"https://api.github.com/repos/angular/angular/issues/24547","repository_url":"https://api.github.com/repos/angular/angular","labels_url":"https://api.github.com/repos/angular/angular/issues/24547/labels{/name}","comments_url":"https://api.github.com/repos/angular/angular/issues/24547/comments","events_url":"https://api.github.com/repos/angular/angular/issues/24547/events","html_url":"https://github.com/angular/angular/issues/24547","id":332989431,"node_id":"MDU6SXNzdWUzMzI5ODk0MzE=","number":24547,"title":"scrollPositionRestoration has several problems","user":{"login":"jnizet","id":1608223,"node_id":"MDQ6VXNlcjE2MDgyMjM=","avatar_url":"https://avatars3.githubusercontent.com/u/1608223?v=4","gravatar_id":"","url":"https://api.github.com/users/jnizet","html_url":"https://github.com/jnizet","followers_url":"https://api.github.com/users/jnizet/followers","following_url":"https://api.github.com/users/jnizet/following{/other_user}","gists_url":"https://api.github.com/users/jnizet/gists{/gist_id}","starred_url":"https://api.github.com/users/jnizet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jnizet/subscriptions","organizations_url":"https://api.github.com/users/jnizet/orgs","repos_url":"https://api.github.com/users/jnizet/repos","events_url":"https://api.github.com/users/jnizet/events{/privacy}","received_events_url":"https://api.github.com/users/jnizet/received_events","type":"User","site_admin":false},"labels":[{"id":375500771,"node_id":"MDU6TGFiZWwzNzU1MDA3NzE=","url":"https://api.github.com/repos/angular/angular/labels/comp:%20router","name":"comp: router","color":"c7def8","default":false,"description":null},{"id":908952645,"node_id":"MDU6TGFiZWw5MDg5NTI2NDU=","url":"https://api.github.com/repos/angular/angular/labels/subtype:%20docs-clarification","name":"subtype: docs-clarification","color":"FFFFFF","default":false,"description":"Doc is not wrong, but it could be more clear"},{"id":130606845,"node_id":"MDU6TGFiZWwxMzA2MDY4NDU=","url":"https://api.github.com/repos/angular/angular/labels/type:%20feature","name":"type: feature","color":"EEEEEE","default":false,"description":null}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/angular/angular/milestones/82","html_url":"https://github.com/angular/angular/milestone/82","labels_url":"https://api.github.com/repos/angular/angular/milestones/82/labels","id":3045967,"node_id":"MDk6TWlsZXN0b25lMzA0NTk2Nw==","number":82,"title":"Backlog","description":"Milestone for triaged issues that have not yet been scheduled for resolution.","creator":{"login":"IgorMinar","id":216296,"node_id":"MDQ6VXNlcjIxNjI5Ng==","avatar_url":"https://avatars3.githubusercontent.com/u/216296?v=4","gravatar_id":"","url":"https://api.github.com/users/IgorMinar","html_url":"https://github.com/IgorMinar","followers_url":"https://api.github.com/users/IgorMinar/followers","following_url":"https://api.github.com/users/IgorMinar/following{/other_user}","gists_url":"https://api.github.com/users/IgorMinar/gists{/gist_id}","starred_url":"https://api.github.com/users/IgorMinar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IgorMinar/subscriptions","organizations_url":"https://api.github.com/users/IgorMinar/orgs","repos_url":"https://api.github.com/users/IgorMinar/repos","events_url":"https://api.github.com/users/IgorMinar/events{/privacy}","received_events_url":"https://api.github.com/users/IgorMinar/received_events","type":"User","site_admin":false},"open_issues":2433,"closed_issues":1794,"state":"open","created_at":"2018-01-18T16:52:20Z","updated_at":"2019-11-20T18:44:38Z","due_on":null,"closed_at":null},"comments":67,"created_at":"2018-06-16T14:05:50Z","updated_at":"2019-11-20T22:21:42Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"<!--\r\nPLEASE HELP US PROCESS GITHUB ISSUES FASTER BY PROVIDING THE FOLLOWING INFORMATION.\r\n\r\nISSUES MISSING IMPORTANT INFORMATION MAY BE CLOSED WITHOUT INVESTIGATION.\r\n-->\r\n\r\n## I'm submitting a...\r\n<!-- Check one of the following options with \"x\" -->\r\n<pre><code>\r\n[ ] Regression (a behavior that used to work and stopped working in a new release)\r\n[x] Bug report  <!-- Please search GitHub for a similar issue or PR before submitting -->\r\n[ ] Performance issue\r\n[x] Feature request\r\n[x] Documentation issue or request\r\n[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question\r\n[ ] Other... Please describe:\r\n</code></pre>\r\n\r\n## Current behavior\r\n<!-- Describe how the issue manifests. -->\r\n\r\nI started experimenting with the new `scrollPositionRestoration` feature in the [RouterModule extra options](https://next.angular.io/api/router/ExtraOptions). I expected scroll restoration to work by default when setting the property to 'enabled', but it doesn't. And the documentation has issues, too.\r\n\r\n## Expected behavior\r\n<!-- Describe what the desired behavior would be. -->\r\n\r\nThe documentation says:\r\n> 'enabled'--set the scroll position to the stored position. This option will be the default in the future.\r\n\r\nSo I naïvely thought that setting the flag to 'enabled' would be sufficient to restore the scroll position. But it isn't. \r\n\r\nIndeed, the scroll event is fired, and the scroll position is restored, before the `ngAfterViewInit` hook of the activated component has been called. So the view of the component is not ready yet when the router tries to restore the scroll position (i.e. there is no way to scroll to the end of a long list, because the list isn't there yet). \r\n\r\nAnd even if it was restored after the view is ready, that would only work if the activated component used a resolved guard to load the data.\r\n\r\nSo, the documentation should, IMHO, at least indicate that restoring the scroll position always requires to\r\n - explicitly intercept the Scroll event, and scroll imperatively after a delay. This can be done in a single place, but I don't see how to do that in a reliable way, since there is no way to know if the delay is sufficient for the data to have been loaded (but it would at least work if resolve guards are used consistently), or\r\n - explicitly intercept the Scroll event in each routed component, and imperatively scroll when the data has been loaded and the view has been rendered. This is not a trivial task.\r\n\r\nI read the remaining of the documentation, which has examples about doing this kind of stuff (although it doesn't really say that they're required). But those examples are all incorrect.\r\n\r\nHere's the first example:\r\n\r\n```\r\n    class AppModule {\r\n     constructor(router: Router, viewportScroller: ViewportScroller, store: Store<AppState>) {\r\n       router.events.pipe(filter(e => e instanceof Scroll), switchMap(e => {\r\n         return store.pipe(first(), timeout(200), map(() => e));\r\n       }).subscribe(e => {\r\n         if (e.position) {\r\n           viewportScroller.scrollToPosition(e.position);\r\n         } else if (e.anchor) {\r\n           viewportScroller.scrollToAnchor(e.anchor);\r\n         } else {\r\n           viewportScroller.scrollToPosition([0, 0]);\r\n         }\r\n       });\r\n     }\r\n    }\r\n```\r\n\r\nThis example uses a Store service, which is not part of Angular (I guess it's part of ngrx). So that makes it hard to understand and adapt for those who don't use ngrx.\r\n\r\nBesides, it doesn't compile, because a closing parenthesis is missing, and because `e` is of type Event, and not of type Scroll, and thus has no `position` property. \r\n\r\nThe second example is the following:\r\n```\r\n    class ListComponent {\r\n      list: any[];\r\n      constructor(router: Router, viewportScroller: ViewportScroller, fetcher: ListFetcher) {\r\n        const scrollEvents = router.events.filter(e => e instanceof Scroll);\r\n        listFetcher.fetch().pipe(withLatestFrom(scrollEvents)).subscribe(([list, e]) => {\r\n          this.list = list;\r\n          if (e.position) {\r\n            viewportScroller.scrollToPosition(e.position);\r\n          } else {\r\n            viewportScroller.scrollToPosition([0, 0]);\r\n          }\r\n        });\r\n      }\r\n    }\r\n```\r\n\r\nIt doesn't compile because it still uses an old, non-pipeable operator, and because, once again, `e` is of type Event, not Scroll.\r\n\r\nBut even after fixing the compilation errors, it doesn't work because the view hasn't been updated with the new list yet when `viewportScroller.scrollToPosition(e.position);` is called. \r\n\r\nSo the code would have to be changed to the following in order to compile and work as expected\r\n\r\n```\r\n    class ListComponent {\r\n      list: any[];\r\n      constructor(router: Router, viewportScroller: ViewportScroller, fetcher: ListFetcher) {\r\n        const scrollEvents = router.events.filter(e => e instanceof Scroll);\r\n        listFetcher.fetch().pipe(withLatestFrom(scrollEvents)).subscribe(([list, e]) => {\r\n          this.races = list;\r\n          const scrollEvent = e as Scroll;\r\n          of(scrollEvent).pipe(delay(1)).subscribe(s => {\r\n            if (s.position) {\r\n              viewportScroller.scrollToPosition(s.position);\r\n            } else {\r\n              viewportScroller.scrollToPosition([0, 0]);\r\n            }\r\n          });\r\n        });\r\n      }\r\n    }\r\n```\r\n\r\nI think that none of these solutions is really simple enough, though. Here are two ideas that could maybe make things easier:\r\n\r\n - only fire the Scroll event and try to restore the position after the ngAfterViewInit hook has been called. This should at least make things work when a resolve guard is used to load the list. Or when the list is available immediately.\r\n - for the other cases, allow to inject a service that the component could call when the list has been loaded. It would be up to this service to get the last scroll position or anchor, to wait until the view has been rendered, and then to restore the scroll position. It would ignore all but the first call after the component has been activated.\r\n\r\n## Minimal reproduction of the problem with instructions\r\n\r\nHere's a repo illustrating the various issues and solutions presented above: https://github.com/jnizet/scrollbug. It's a standard angular-cli project. I can't run it in stackblitz unfortunately (probably because Stackblitz doesn't support the beta release of Angular).\r\n\r\n## What is the motivation / use case for changing the behavior?\r\n<!-- Describe the motivation or the concrete use case. -->\r\n\r\nFirst, the documentation should be fixed and made clearer\r\n1. it should not use ngrx\r\n2. it should contain examples that compile, and run as expected\r\n3. it should make it clear than simply setting the flag to 'enabled' is not sufficient to enable scroll restoration \r\n\r\nSecond, it should be way easier to make that feature work. See ideas above.\r\n\r\n## Environment\r\n\r\n<pre><code>\r\nAngular version: 6.1.0-beta.1\r\n<!-- Check whether this is still an issue in the most recent Angular version -->\r\n\r\nBrowser:\r\n- [x] Chrome (desktop) version 67.0.3396.87\r\n- [ ] Chrome (Android) version XX\r\n- [ ] Chrome (iOS) version XX\r\n- [x] Firefox version 60.0.2 \r\n- [ ] Safari (desktop) version XX\r\n- [ ] Safari (iOS) version XX\r\n- [ ] IE version XX\r\n- [ ] Edge version XX\r\n \r\n</code></pre>\r\n"},"comment":{"url":"https://api.github.com/repos/angular/angular/issues/comments/556478813","html_url":"https://github.com/angular/angular/issues/24547#issuecomment-556478813","issue_url":"https://api.github.com/repos/angular/angular/issues/24547","id":556478813,"node_id":"MDEyOklzc3VlQ29tbWVudDU1NjQ3ODgxMw==","user":{"login":"mattcwebster","id":43913755,"node_id":"MDQ6VXNlcjQzOTEzNzU1","avatar_url":"https://avatars1.githubusercontent.com/u/43913755?v=4","gravatar_id":"","url":"https://api.github.com/users/mattcwebster","html_url":"https://github.com/mattcwebster","followers_url":"https://api.github.com/users/mattcwebster/followers","following_url":"https://api.github.com/users/mattcwebster/following{/other_user}","gists_url":"https://api.github.com/users/mattcwebster/gists{/gist_id}","starred_url":"https://api.github.com/users/mattcwebster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattcwebster/subscriptions","organizations_url":"https://api.github.com/users/mattcwebster/orgs","repos_url":"https://api.github.com/users/mattcwebster/repos","events_url":"https://api.github.com/users/mattcwebster/events{/privacy}","received_events_url":"https://api.github.com/users/mattcwebster/received_events","type":"User","site_admin":false},"created_at":"2019-11-20T22:21:42Z","updated_at":"2019-11-20T22:21:42Z","author_association":"NONE","body":"is there any date on resolution for this.  Just discovered today on my app and is depressing to know the the scrollRestoration: enabled property doesn't work as expected.  For me it works on mobile though which is odd."}}
other: {"actor":{"display_login":"mattcwebster"}}