답변:
최신 정보
이제 지원됩니다.
<a [routerLink]="['somepath']" fragment="Test">Jump to 'Test' anchor </a>
this._router.navigate( ['/somepath', id ], {fragment: 'test'});
스크롤하려면 구성 요소에 아래 코드를 추가하십시오.
import {ActivatedRoute} from '@angular/router'; // <-- do not forget to import
private fragment: string;
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.route.fragment.subscribe(fragment => { this.fragment = fragment; });
}
ngAfterViewInit(): void {
try {
document.querySelector('#' + this.fragment).scrollIntoView();
} catch (e) { }
}
실물
이것은 알려진 문제이며 https://github.com/angular/angular/issues/6595 에서 추적됩니다.
01
여부를 염두에 두십시오 100
. 유효한 선택 자로 만들기 위해 문자 또는 기타를 추가 할 수 있습니다. 따라서 여전히 01
조각으로 전달 되지만는 id
다음과 같아야 d01
하므로 document.querySelector('#d'+id)
일치합니다.
Günter의 대답 은 정확 하지만 앵커 태그 부분으로 "점프"하는 부분은 다루지 않습니다 .
따라서 다음에 추가로 :
<a [routerLink]="['somepath']" fragment="Test">Jump to 'Test' anchor </a>
this._router.navigate( ['/somepath', id ], {fragment: 'test'});
... "점프"동작이 필요한 구성 요소 (부모)에 다음을 추가합니다.
import { Router, NavigationEnd } from '@angular/router';
class MyAppComponent {
constructor(router: Router) {
router.events.subscribe(s => {
if (s instanceof NavigationEnd) {
const tree = router.parseUrl(router.url);
if (tree.fragment) {
const element = document.querySelector("#" + tree.fragment);
if (element) { element.scrollIntoView(true); }
}
}
});
}
}
이것은 해결 방법입니다 . 향후 업데이트를 위해이 github 문제 를 따르십시오 . 크레딧 빅터 Savkin 솔루션을 제공!
"['../faq']"
하려면 값을 지정해야합니다. 그렇지 않으면 / faq / faq / # anchor, insteaf of / faq / # anchor로 이동하려고합니다. 이것이 올바른 방법입니까, 아니면 routerlink에서 현재 페이지를 참조하는 더 우아한 방법이 있습니까? 또한 document.querySelector("#" + tree.fragment);
유효한 선택기 오류가 아닙니다. 이것이 맞습니까? Thank you
<a [routerLink]="['/faq']" fragment="section6">
?
조금 늦게 대답해서 죄송합니다. Angular Routing Documentation에는 해시 태그를 페이지 앵커로 라우팅하는 데 도움이되는 미리 정의 된 기능이 있습니다. 예 : anchorScrolling : 'enabled'
단계 -1 :- 먼저 app.module.ts 파일에서 RouterModule 을 가져옵니다 .
imports:[
BrowserModule,
FormsModule,
RouterModule.forRoot(routes,{
anchorScrolling: 'enabled'
})
],
2 단계 : -HTML 페이지로 이동하여 탐색을 만들고 [routerLink] 와 같은 두 가지 중요한 속성을 추가 하고 각 Div ID 를 일치시키기 위해 조각 을 추가합니다 .
<ul>
<li> <a [routerLink] = "['/']" fragment="home"> Home </a></li>
<li> <a [routerLink] = "['/']" fragment="about"> About Us </a></li>
<li> <a [routerLink] = "['/']" fragment="contact"> Contact Us </a></li>
</ul>
3 단계 : -ID 이름 을 조각 과 일치시켜 섹션 / div를 만듭니다 .
<section id="home" class="home-section">
<h2> HOME SECTION </h2>
</section>
<section id="about" class="about-section">
<h2> ABOUT US SECTION </h2>
</section>
<section id="contact" class="contact-section">
<h2> CONTACT US SECTION </h2>
</section>
참고로 문제를 해결하는 데 도움이되는 작은 데모를 만들어 아래 예제를 추가했습니다.
scrollPositionRestoration: 'enabled',
:) anchorScrolling 옵션에
조금 늦었지만 여기에 작동하는 답변이 있습니다.
<a [routerLink]="['/path']" fragment="test" (click)="onAnchorClick()">Anchor</a>
그리고 구성 요소에서 :
constructor( private route: ActivatedRoute, private router: Router ) {}
onAnchorClick ( ) {
this.route.fragment.subscribe ( f => {
const element = document.querySelector ( "#" + f )
if ( element ) element.scrollIntoView ( element )
});
}
위의 내용은 이미 앵커가있는 페이지에 도달하면 뷰로 자동으로 스크롤되지 않으므로 ngInit에서도 위의 솔루션을 사용하여 함께 작동 할 수 있습니다.
ngOnInit() {
this.router.events.subscribe(s => {
if (s instanceof NavigationEnd) {
const tree = this.router.parseUrl(this.router.url);
if (tree.fragment) {
const element = document.querySelector("#" + tree.fragment);
if (element) { element.scrollIntoView(element); }
}
}
});
}
구성 요소의 시작 부분에서 Router, ActivatedRoute 및 NavigationEnd를 가져와야합니다.
document.querySelector ( "#" + f )
은 문자열이 아닌 선택기를 기대하기 때문에 오류를 발생시킵니다.
element.scrollIntoView()
( element
함수에 전달하지 않고 ). 부드럽게 만들려면 다음을 사용하십시오 element.scrollIntoView({block: "end", behavior: "smooth"})
..
onAnchorClick()
에서 scrollIntoView :에 부울을 전달해야 함을 보여줍니다 if (element) { element.scrollIntoView(true); }
. 이제 동일한 링크를 두 번 클릭하고 작품을 스크롤 할 수 있습니다
이전 답변 중 어느 것도 나를 위해 일하지 않았습니다. 마지막 도랑 노력에서 내 템플릿을 시도했습니다.
<a (click)="onClick()">From Here</a>
<div id='foobar'>To Here</div>
내 .ts에서 이것으로 :
onClick(){
let x = document.querySelector("#foobar");
if (x){
x.scrollIntoView();
}
}
그리고 내부 링크에 대해 예상대로 작동합니다. 실제로 앵커 태그를 사용하지 않으므로 URL을 전혀 건드리지 않습니다.
위의 솔루션이 저에게 효과적이지 않았습니다.
먼저 ngAfterViewChecked ()MyAppComponent
에서 자동 스크롤을 준비하십시오 .
import { Component, OnInit, AfterViewChecked } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
@Component( {
[...]
} )
export class MyAppComponent implements OnInit, AfterViewChecked {
private scrollExecuted: boolean = false;
constructor( private activatedRoute: ActivatedRoute ) {}
ngAfterViewChecked() {
if ( !this.scrollExecuted ) {
let routeFragmentSubscription: Subscription;
// Automatic scroll
routeFragmentSubscription =
this.activatedRoute.fragment
.subscribe( fragment => {
if ( fragment ) {
let element = document.getElementById( fragment );
if ( element ) {
element.scrollIntoView();
this.scrollExecuted = true;
// Free resources
setTimeout(
() => {
console.log( 'routeFragmentSubscription unsubscribe' );
routeFragmentSubscription.unsubscribe();
}, 1000 );
}
}
} );
}
}
}
그런 다음 해시 태그 my-app-route
보내기로 이동합니다.prodID
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component( {
[...]
} )
export class MyOtherComponent {
constructor( private router: Router ) {}
gotoHashtag( prodID: string ) {
this.router.navigate( [ '/my-app-route' ], { fragment: prodID } );
}
}
다른 모든 답변은 Angular 버전 <6.1에서 작동합니다. 그러나 최신 버전을 가지고 있다면 Angular가 문제를 해결 했으므로 이러한 추악한 해킹을 할 필요가 없습니다.
여러분이해야 할 일은 method scrollOffset
의 두 번째 인자 옵션으로 설정 하는 것뿐입니다 RouterModule.forRoot
.
@NgModule({
imports: [
RouterModule.forRoot(routes, {
scrollPositionRestoration: 'enabled',
anchorScrolling: 'enabled',
scrollOffset: [0, 64] // [x, y]
})
],
exports: [RouterModule]
})
export class AppRoutingModule {}
html 파일에서 :
<a [fragment]="test1" [routerLink]="['./']">Go to Test 1 section</a>
<section id="test1">...</section>
<section id="test2">...</section>
ts 파일에서 :
export class PageComponent implements AfterViewInit, OnDestroy {
private destroy$$ = new Subject();
private fragment$$ = new BehaviorSubject<string | null>(null);
private fragment$ = this.fragment$$.asObservable();
constructor(private route: ActivatedRoute) {
this.route.fragment.pipe(takeUntil(this.destroy$$)).subscribe(fragment => {
this.fragment$$.next(fragment);
});
}
public ngAfterViewInit(): void {
this.fragment$.pipe(takeUntil(this.destroy$$)).subscribe(fragment => {
if (!!fragment) {
document.querySelector('#' + fragment).scrollIntoView();
}
});
}
public ngOnDestroy(): void {
this.destroy$$.next();
this.destroy$$.complete();
}
}
Kalyoyan의 답변 에 추가하면 이 구독은 라우터에 연결되어 페이지가 완전히 새로 고쳐질 때까지 유지됩니다. 구성 요소에서 라우터 이벤트를 구독 할 때 ngOnDestroy에서 구독을 취소해야합니다.
import { OnDestroy } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { Subscription } from "rxjs/Rx";
class MyAppComponent implements OnDestroy {
private subscription: Subscription;
constructor(router: Router) {
this.subscription = router.events.subscribe(s => {
if (s instanceof NavigationEnd) {
const tree = router.parseUrl(router.url);
if (tree.fragment) {
const element = document.querySelector("#" + tree.fragment);
if (element) { element.scrollIntoView(element); }
}
}
});
}
public ngOnDestroy() {
this.subscription.unsubscribe();
}
}
방금 내 웹 사이트에서이 작업을 수행했기 때문에 여기에 내 솔루션을 게시 할 가치가 있다고 생각했습니다.
<a [routerLink]="baseUrlGoesHere" fragment="nameOfYourAnchorGoesHere">Link Text!</a>
<a name="nameOfYourAnchorGoesHere"></a>
<div>They're trying to anchor to me!</div>
그런 다음 구성 요소에 다음을 포함해야합니다.
import { ActivatedRoute } from '@angular/router';
constructor(private route: ActivatedRoute) {
this.route.fragment.subscribe ( f => {
const element = document.querySelector ( "#" + f )
if ( element ) element.scrollIntoView ( element )
});
}
element.scrollIntoView()
또는 element.scrollIntoView(true)
. 귀하의 버전이 나를 위해 컴파일되지 않았습니다 (아마도 strictNullChecks 때문입니까?).
모든 솔루션을 읽은 후 구성 요소를 찾고 원래 질문에서 요청한 것과 정확히 일치하는 구성 요소를 찾았습니다. 앵커 링크로 스크롤. https://www.npmjs.com/package/ng2-scroll-to
설치할 때 다음과 같은 구문을 사용합니다.
// app.awesome.component.ts
@Component({
...
template: `...
<a scrollTo href="#main-section">Scroll to main section</a>
<button scrollTo scrollTargetSelector="#test-section">Scroll to test section</a>
<button scrollTo scrollableElementSelector="#container" scrollYTarget="0">Go top</a>
<!-- Further content here -->
<div id="container">
<section id="main-section">Bla bla bla</section>
<section id="test-section">Bla bla bla</section>
<div>
...`,
})
export class AwesomeComponent {
}
그것은 나를 위해 정말 잘 작동했습니다.
쿼리 매개 변수가없는 페이지에서 작동하는 간단한 솔루션은 브라우저 뒤로 / 앞으로, 라우터 및 딥 링크 호환입니다.
<a (click)="jumpToId('anchor1')">Go To Anchor 1</a>
ngOnInit() {
// If your page is dynamic
this.yourService.getWhatever()
.then(
data => {
this.componentData = data;
setTimeout(() => this.jumpToId( window.location.hash.substr(1) ), 100);
}
);
// If your page is static
// this.jumpToId( window.location.hash.substr(1) )
}
jumpToId( fragment ) {
// Use the browser to navigate
window.location.hash = fragment;
// But also scroll when routing / deep-linking to dynamic page
// or re-clicking same anchor
if (fragment) {
const element = document.querySelector('#' + fragment);
if (element) element.scrollIntoView();
}
}
시간 제한은 단순히 페이지가 * ngIf에 의해 "보호 된"동적 데이터를로드하도록 허용하는 것입니다. 경로를 변경할 때 페이지 상단으로 스크롤하는데도 사용할 수 있습니다. 기본 상단 앵커 태그 만 제공하면됩니다.
URL에 해당 요소 ID를 추가하는 것이 중요하지 않은 경우 다음 링크를 살펴 보는 것이 좋습니다.
Angular 2-현재 페이지의 요소에 대한 앵커 링크
// html
// add (click) event on element
<a (click)="scroll({{any-element-id}})">Scroll</a>
// in ts file, do this
scroll(sectionId) {
let element = document.getElementById(sectionId);
if(element) {
element.scrollIntoView(); // scroll to a particular element
}
}
JavierFuentes 답변을 참조하는 또 다른 해결 방법은 다음과 같습니다.
<a [routerLink]="['self-route', id]" fragment="some-element" (click)="gotoHashtag('some-element')">Jump to Element</a>
스크립트에서 :
import {ActivatedRoute} from "@angular/router";
import {Subscription} from "rxjs/Subscription";
export class Links {
private scrollExecuted: boolean = false;
constructor(private route: ActivatedRoute) {}
ngAfterViewChecked() {
if (!this.scrollExecuted) {
let routeFragmentSubscription: Subscription;
routeFragmentSubscription = this.route.fragment.subscribe(fragment => {
if (fragment) {
let element = document.getElementById(fragment);
if (element) {
element.scrollIntoView();
this.scrollExecuted = true;
// Free resources
setTimeout(
() => {
console.log('routeFragmentSubscription unsubscribe');
routeFragmentSubscription.unsubscribe();
}, 0);
}
}
});
}
}
gotoHashtag(fragment: string) {
const element = document.querySelector("#" + fragment);
if (element) element.scrollIntoView(element);
}
}
이렇게하면 사용자가 URL에 해시 태그가있는 페이지에 직접 방문하는 경우 요소로 직접 스크롤 할 수 있습니다.
그러나이 경우에는 Route Fragment를 구독 ngAfterViewChecked
했지만 ngAfterViewChecked()
매번 계속 호출되며 ngDoCheck
사용자가 맨 위로 스크롤 할 수 없으므로 routeFragmentSubscription.unsubscribe
뷰가 요소로 스크롤 된 후 0 밀리 초의 타임 아웃 후에 호출됩니다.
또한 gotoHashtag
사용자가 특정 앵커 태그를 클릭 할 때 요소로 스크롤하는 방법이 정의되어 있습니다.
최신 정보:
URL에 쿼리 문자열이 있으면 [routerLink]="['self-route', id]"
앵커에서 쿼리 문자열을 유지하지 않습니다. 동일한 해결 방법을 시도했습니다.
<a (click)="gotoHashtag('some-element')">Jump to Element</a>
constructor( private route: ActivatedRoute,
private _router:Router) {
}
...
...
gotoHashtag(fragment: string) {
let url = '';
let urlWithSegments = this._router.url.split('#');
if(urlWithSegments.length){
url = urlWithSegments[0];
}
window.location.hash = fragment;
const element = document.querySelector("#" + fragment);
if (element) element.scrollIntoView(element);
}
이것은 나를 위해 작동합니다!! 이 ngFor는 태그를 동적으로 고정하므로 렌더링을 기다려야합니다.
HTML :
<div #ngForComments *ngFor="let cm of Comments">
<a id="Comment_{{cm.id}}" fragment="Comment_{{cm.id}}" (click)="jumpToId()">{{cm.namae}} Reply</a> Blah Blah
</div>
내 TS 파일 :
private fragment: string;
@ViewChildren('ngForComments') AnchorComments: QueryList<any>;
ngOnInit() {
this.route.fragment.subscribe(fragment => { this.fragment = fragment;
});
}
ngAfterViewInit() {
this.AnchorComments.changes.subscribe(t => {
this.ngForRendred();
})
}
ngForRendred() {
this.jumpToId()
}
jumpToId() {
let x = document.querySelector("#" + this.fragment);
console.log(x)
if (x){
x.scrollIntoView();
}
}
그 가져올 것을 잊지 마십시오 ViewChildren
, QueryList
등 .. 일부 생성자를 추가 ActivatedRoute
!
다른 답변과 달리 추가 focus()
로 scrollIntoView()
. 또한 setTimeout
URL을 변경할 때 맨 위로 점프하기 때문에 사용 하고 있습니다. 그 이유가 무엇인지 확실 setTimeout
하지 않지만 해결 방법이있는 것 같습니다 .
유래:
<a [routerLink] fragment="some-id" (click)="scrollIntoView('some-id')">Jump</a>
목적지:
<a id="some-id" tabindex="-1"></a>
Typescript :
scrollIntoView(anchorHash) {
setTimeout(() => {
const anchor = document.getElementById(anchorHash);
if (anchor) {
anchor.focus();
anchor.scrollIntoView();
}
});
}
나는 같은 문제가 있었다. 해결책 : View port Scroller https://angular.io/api/common/ViewportScroller#scrolltoanchor 사용
-app-routing.module.ts 코드 :
import { PageComponent } from './page/page.component';
const routes: Routes = [
path: 'page', component: PageComponent },
path: 'page/:id', component: PageComponent }
];
-컴포넌트 HTML
<a (click) = "scrollTo('typeExec')">
<mat-icon>lens</mat-icon>
</a>
-구성 요소 코드 :
import { Component } from '@angular/core';
import { ViewportScroller } from '@angular/common';
export class ParametrageComponent {
constructor(private viewScroller: ViewportScroller) {}
scrollTo(tag : string)
{
this.viewScroller.scrollToAnchor(tag);
}
}
나는 nmp-ngx-scroll-to 에서 사용 가능한 매우 유용한 플러그인을 테스트했습니다 . 그러나 Angular 4+ 용으로 설계되었지만 누군가이 답변이 도움이 될 것입니다.
나는 이러한 솔루션의 대부분을 시도했지만 작동하지 않을 다른 조각으로 돌아가는 문제가 발생했기 때문에 100 % 작동하는 약간 다른 작업을 수행하고 URL에서 추악한 해시를 제거했습니다.
여기에 내가 지금까지 본 것보다 더 나은 방법이 있습니다.
import { Component, OnInit, AfterViewChecked, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector: 'app-hero',
templateUrl: './hero.component.html',
styleUrls: ['./hero.component.scss']
})
export class HeroComponent implements OnInit, AfterViewChecked, OnDestroy {
private fragment: string;
fragSub: Subscription;
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.fragSub = this.route.fragment.subscribe( fragment => { this.fragment = fragment; })
}
ngAfterViewChecked(): void {
try {
document.querySelector('#' + this.fragment).scrollIntoView({behavior: 'smooth'});
window.location.hash = "";
} catch (e) { }
}
ngOnDestroy() {
this.fragSub.unsubscribe();
}
}
123
경로 경로가 다음과 같은 매개 변수를 예상한다고 가정 하고 문자열 (예 : 질문 내용)이있는 변수를{ path: 'users/:id', ....}