I am trying to do a simple scroll to an anchor element on the same page. Basically, the person clicks on a "Try It" button and it scrolls to an area lower on the page with the id "login". Right now, it is working with a basic id="login"
& <a href="#login"></a>
but it is jumping to that section. Ideally, I would like it to scroll there. If I am using Angular4, is there some built in way to do this or what is the easiest way? Thanks!
Whole template... (component still empty)
<div id="image-header">
<div id="intro">
<h1 class="text-center">Welcome to ThinkPlan</h1>
<h3 class="text-center">Planning your way</h3>
<a class="btn btn-outline-primary" href="#login" id="view">Try It</a> <!-- Where the user clicks to scroll -->
</div>
</div>
<div class="container" id="info">
<div class="row">
<div class="col-md-12">
<div class="space" id="login"></div> <!-- The place to scroll to -->
<h1 class="text-center">ThinkPlan</h1>
<form class="form-horizontal">
<fieldset>
<legend>Login</legend>
<div class="form-group">
<label for="inputEmail" class="col-lg-2 control-label">Email</label>
<div class="col-lg-10">
<input type="text" class="form-control" id="inputEmail" placeholder="Email">
</div>
</div>
<div class="form-group">
<label for="inputPassword" class="col-lg-2 control-label">Password</label>
<div class="col-lg-10">
<input type="password" class="form-control" id="inputPassword" placeholder="Password">
</div>
</div>
<div class="form-group" id="log-btn">
<div class="col-lg-10 col-lg-offset-2">
<button routerLink="/plan" type="submit" class="btn btn-outline-primary">Login</button>
</div>
</div>
<p class="lead text-center">New here? <a routerLink="signup">Sign up.</a></p>
</fieldset>
</form>
</div>
</div>
</div>
I think it's more simple solution :
In your HTML :
<a [routerLink]="['/']" fragment="login"></a>
In your typescript :
ngOnInit() {
this.route.fragment.subscribe(fragment => { this.fragment = fragment; });
}
ngAfterViewChecked(): void {
try {
if(this.fragment) {
document.querySelector('#' + this.fragment).scrollIntoView();
}
} catch (e) { }
}
Automatic Scrolling
Since Angular v6, there is the new anchorScrolling
option for the RouterModule
. You can set it in the module's import:
imports: [
...,
RouterModule.forRoot(routes, {anchorScrolling: 'enabled'})
With this, Angular will automatically scroll to the element with the id of the given fragment.
⚠️ However, this does not work when the data is loaded asynchronously, see this Github issue. ⚠️
Manual Scrolling
Smooth scrolling is not yet possible via the RouterModule
, but you can do it manually:
1) Get your target e.g. with ViewChild
:
@ViewChild('pageInfo') pageInfo: ElementRef;
2) Call scrollIntoView
on the nativeElement
:
const targetElement = this.pageInfo.nativeElement
targetElement.scrollIntoView({behavior: "smooth"})
With Angular 4 you can have some problem using anchor to the same page.
I solved using this way
install
npm install ng2-page-scroll --save
import in your app.module.ts
import {Ng2PageScrollModule} from 'ng2-page-scroll';
@NgModule({
imports: [
/* Other imports here */
Ng2PageScrollModule
]
})
export class AppModule {
}
test it in your html component
<a pageScroll href="#test">Testing</a>
<div id="test">
AfterViewCheck()
will be called every time the ChangeDetection
is triggered, so it is a bad solution.
Use AfterViewInit()
like
public ngAfterViewInit(): void {
this.subscription = this.route.fragment
.subscribe(fragment => {
const targetElement = this.document.querySelector('#' + fragment);
if (fragment && targetElement) {
targetElement.scrollIntoView();
} else {
window.scrollTo(0, 0);
}
});
}
public ngOnDestroy(): void {
this.subscription.unsubscribe();
}
This is a more detailed example to add to Sarah Dubois' answer above.
Import router modules.
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
constructor(private route:ActivatedRoute,
private router:Router) {
router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
if (event.url) {
this.route.fragment.subscribe(fragment => this.fragment = fragment);
}
}
});
}
ngAfterViewChecked(): void {
try {
if(this.fragment != null) {
document.querySelector("a[name="+this.fragment+"]").scrollIntoView();
}
} catch (e) {
//console.log(e, 'error');
}
}
I like the use of querySelector which will give you a lot of options to which element you would like to scroll to. https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
This works with Angular 8 :)
来源:https://stackoverflow.com/questions/44441089/angular4-scrolling-to-anchor