Discussion for angular (2+) - need help? create a stackblitz with your issue to get help faster using this template: https://stackblitz.com/fork/angular-issue-repro2
@Injectable({
providedIn: 'root',
useFactory: (document, window, handler: ErrorHandler) => new ShopScrollerService(
document,
document.querySelector('.mat-sidenav-content'),
handler
),
deps: [DOCUMENT, ErrorHandler]
})
export class ShopScrollerService implements ViewportScroller {
private offset: () => [number, number] = () => [0, 0];
constructor(private document: Document, private window: any, private errorHandler: ErrorHandler) {
setTimeout(() => {
this.window = document.querySelector('.mat-sidenav-content');
}, 1000)
}
/**
* Configures the top offset used when scrolling to an anchor.
* @param offset A position in screen coordinates (a tuple with x and y values)
* or a function that returns the top offset position.
*
*/
setOffset(offset: [number, number]|(() => [number, number])): void {
if (Array.isArray(offset)) {
this.offset = () => offset;
} else {
this.offset = offset;
}
}
/**
* Retrieves the current scroll position.
* @returns The position in screen coordinates.
*/
getScrollPosition(): [number, number] {
if (this.supportScrollRestoration() && this.window instanceof Window) {
return [this.window.scrollX, this.window.scrollY];
}
else if(this.supportScrollRestoration() && this.window instanceof HTMLElement){
return [this.window.scrollLeft, this.window.scrollTop]
}
else {
return [0, 0];
}
}
/**
* Sets the scroll position.
* @param position The new position in screen coordinates.
*/
scrollToPosition(position: [number, number]): void {
if (this.supportScrollRestoration()) {
this.window.scrollTo(position[0], position[1]);
}
}
/**
* Scrolls to an anchor element.
* @param anchor The ID of the anchor element.
*/
scrollToAnchor(anchor: string): void {
if (this.supportScrollRestoration()) {
// Escape anything passed to `querySelector` as it can throw errors and stop the application
// from working if invalid values are passed.
if (this.window.CSS && this.window.CSS.escape) {
anchor = this.window.CSS.escape(anchor);
} else {
anchor = anchor.replace(/(\"|\'\ |:|\.|\[|\]|,|=)/g, '\\$1');
}
try {
const elSelectedById = this.document.querySelector(`#${anchor}`);
if (elSelectedById) {
this.scrollToElement(elSelectedById);
return;
}
const elSelectedByName = this.document.querySelector(`[name='${anchor}']`);
if (elSelectedByName) {
this.scrollToElement(elSelectedByName);
return;
}
} catch (e) {
this.errorHandler.handleError(e);
}
}
}
/**
* Disables automatic scroll restoration provided by the browser.
*/
setHistoryScrollRestoration(scrollRestoration: 'auto'|'manual'): void {
if (this.supportScrollRestoration()) {
const history = this.window.history;
if (history && history.scrollRestoration) {
history.scrollRestoration = scrollRestoration;
}
}
}
private scrollToElement(el: any): void {
const rect = el.getBoundingClientRect();
const left = rect.left + this.window.pageXOffset;
const top = rect.top + this.window.pageYOffset;
const offset = this.offset();
this.window.scrollTo(left - offset[0], top - offset[1]);
}
/**
* We only support scroll restoration when we can get a hold of window.
* This means that we do not support this behavior when running in a web worker.
*
* Lifting this restriction right now would require more changes in the dom adapter.
* Since webworkers aren't widely used, we will lift it once RouterScroller is
* battle-tested.
*/
private supportScrollRestoration(): boolean {
try {
return !!this.window && !!this.window.scrollTo;
} catch {
return false;
}
}
}
Window
to be scrolled.
setTimeout
i laid out above is just a bad hack I threw together.
scroll
event triggers after ngAfterViewInit
How can i animate a transition between the same component ( via a router )
the way i have my route set is that we just re-use the same component, and get different data using a route resolver. this is used for a category page, with an unlimited number of sub categories (e.g cat one has 2 subcats, one of the subcats has more ... etc)