Маршрутизация Angular2 с хэштегом для привязки страницы

Я хочу добавить несколько ссылок на мою страницу Angular2, которые при нажатии будут переходить на определенные позиции внутри этой страницы, как это делают обычные хэштеги. Так что ссылки будут примерно такими

/users/123#userInfo
/users/123#userPhoto
/users/123#userLikes

и Т. Д.

Я не думаю, что мне нужен HashLocationStrategy, так как меня устраивает обычный способ Angular2, но если я добавлю напрямую, ссылка фактически перейдет в корень, а не где-то на той же странице. Любое направление приветствуется, спасибо.


person Stone    schedule 19.03.2016    source источник


Ответы (21)


Обновить

Теперь это поддерживается

<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

person Günter Zöchbauer    schedule 19.03.2016
comment
к чему относится id? - person invot; 06.09.2016
comment
@invot переменная со строкой (например, что 123 в вопросе), предполагая, что путь маршрута ожидает такой параметр, как { path: 'users/:id', ....} - person Günter Zöchbauer; 06.09.2016
comment
Что делать, если я хочу, чтобы #anchor отображался только в том случае, если фрагмент не является нулевым/неопределенным? В настоящее время у меня все еще есть somethi.ng/page#. Если привязки нет, это должен быть просто somethi.ng/page. Если есть якорь, обычно он должен быть somethi.ng/page#anchor. - person Kunepro; 17.11.2016
comment
Если вы хотите перейти к якорю, см. этот пост: github.com/angular/angular/issues/ 6595 - person pearpages; 11.01.2017
comment
Примечание: это все еще не прокручивается - person Martín Coll; 14.02.2017
comment
@GünterZöchbauer последнее изменение не прокручивается вместе со мной - person Amr Ibrahim; 21.09.2017
comment
@amrabdulaziz Я не был уверен, что ваше редактирование было лучшим решением. Спасибо, в любом случае :). У меня нет проекта, чтобы попробовать это. Не могли бы вы попробовать обернуть document.querySelector('#' + this.fragment).scrollIntoView(); с setTimeout(() { ...}), чтобы посмотреть, работает ли это таким образом? - person Günter Zöchbauer; 21.09.2017
comment
да, это работает с setTimeout, если я найду лучшее решение, я дам вам знать - person Amr Ibrahim; 21.09.2017
comment
@GünterZöchbauer GünterZöchbauer работает ли это также, если ссылка маршрутизатора находится на расстоянии нескольких компонентов от якоря (дочернего элемента)? - person mpro; 01.03.2018
comment
@mpro По крайней мере, так должно работать. Вопрос все еще открыт, поэтому он может вообще не работать. Я сам не использовал его с тех пор. - person Günter Zöchbauer; 01.03.2018
comment
Для тех, кто изо всех сил пытается прокрутить до числовых идентификаторов, имейте в виду, что 01 или 100 не являются допустимыми селекторами CSS. Возможно, вы захотите добавить букву или что-то еще, чтобы сделать его действительным селектором. Таким образом, вы по-прежнему будете передавать 01 как фрагмент, но id должно быть чем-то вроде d01и, таким образом, document.querySelector('#d'+id) будет соответствовать. - person pop; 16.03.2018
comment
Я добавил свое решение, чтобы оно прокручивалось и на той же странице. просто добавьте это в тег <a>: (click)="window.location = '#Test';" - person Worthy7; 19.09.2018
comment
это решение дает мне эту ошибку Синтаксическая ошибка, нераспознанное выражение: /service-details/1139#overview, потому что нет пути, который включает # parth, так что теперь делать @GünterZöchbauer - person Aarsh; 21.12.2018

Извините, что ответил немного поздно; В документации по маршрутизации Angular есть предопределенная функция, которая помогает нам в маршрутизации с помощью хэштега для привязки страницы, т. е. anchorScrolling: 'enabled'.

Шаг 1.  Сначала импортируйте RouterModule в файл app.module.ts:

imports:[ 
    BrowserModule, 
    FormsModule,
    RouterModule.forRoot(routes,{
      anchorScrolling: 'enabled'
    })
  ],

Шаг 2.  Перейдите на HTML-страницу, создайте навигацию и добавьте два важных атрибута, например [routerLink] и fragment, для сопоставления с соответствующим Идентификаторы Div: –

<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.  Создайте раздел/раздел, сопоставив имя идентификатора с фрагментом: –

<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>

Для справки я добавил приведенный ниже пример, создав небольшую демонстрацию, которая поможет решить вашу проблему.

Демо: https://routing-hashtag-page-anchors.stackblitz.io/

person Naheed Shareef    schedule 29.10.2018
comment
Большое спасибо за это. Чисто, лаконично и работает! - person Belmiris; 31.12.2018
comment
Да, спасибо, для автоматической прокрутки при загрузке страницы с помощью Angular 7 просто нужно добавить scrollPositionRestoration: 'enabled', в параметре anchorScrolling :) - person Mickaël; 31.01.2019
comment
Это правильно добавляет хэш в конец моего URL-адреса, но не привязывает его к div с тем же именем. Я не уверен, что мне не хватает. Я выполнил три шага выше. - person oaklandrichie; 21.08.2019
comment
@oaklandrichie: Можете ли вы поделиться здесь кодом jsfiddle / stackblitz. я могу помочь тебе - person Naheed Shareef; 22.08.2019
comment
этот ответ определенно должен быть принят, работает как шарм! - person Kiss Koppány; 30.03.2020
comment
Спасибо, чувак! Это именно то, что я искал. Единственное, когда это не работает, это когда пользователь нажимает на ту же ссылку второй раз (когда фрагмент уже существует в URL-адресе). Но мне удалось найти еще один параметр для параметров маршрутизации: onSameUrlNavigation: 'reload', который помогает в таких случаях. (Используйте этот параметр вместе с anchorScrolling: 'enabled') - person Aviw; 08.11.2020

Хотя ответ Гюнтера правильный, он не распространяется на "переход" к части тега привязки.

Поэтому дополнительно к:

<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 для будущих обновлений. Спасибо Виктору Савкину за предоставление решения!

person Kaloyan Kosev    schedule 26.05.2017
comment
привет, я делаю страницу часто задаваемых вопросов, где вы можете перейти к ответу, щелкнув вопрос, определенный в списке вверху страницы. Таким образом, пользователь уже находится на текущей странице, когда переходит к якорю. Если я хочу, чтобы атрибут routerLink работал, я должен указать "['../faq']" в качестве значения, иначе он попытается перейти к /faq/faq/#anchor вместо /faq/#anchor. Это правильный способ сделать это или есть более элегантный способ сослаться на текущую страницу в routerlink? Кроме того, document.querySelector("#" + tree.fragment); дает мне недопустимую ошибку селектора. Вы уверены, что это правильно? Спасибо. - person Maurice; 24.06.2018
comment
при повторном нажатии на ту же ссылку она не работает. Кто-нибудь делал это, если пользователь нажимал на ту же якорную ссылку <a [routerLink]="['/faq']" fragment="section6">? - person Junior Mayhé; 29.08.2018
comment
@JuniorM Вы когда-нибудь это понимали? Я столкнулся с той же проблемой. - person The Muffin Man; 28.10.2018
comment
@Muffin, попробуйте что-нибудь вроде этого github.com/juniormayhe/Mailing/blob/master/Mailing.SPA/src/app/ - person Junior Mayhé; 30.10.2018
comment
Это требует большей экспозиции. Это лучший ответ ИМО. Большинство людей захотят перейти к разделу. - person iamtravisw; 15.09.2019

Немного поздно, но вот ответ, который я нашел, который работает:

<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 в начале вашего компонента, и все должно быть в порядке.

Источник

person Ali Bari    schedule 31.05.2017
comment
Работает на меня! Если вы хотите перемещаться по той же странице, на которой вы уже находитесь, используйте [routerLink]=['.'] - person Raoul; 11.02.2018
comment
не могли бы вы объяснить дальше? эта часть document.querySelector ( "#" + f ) дает мне ошибку, потому что она ожидает селектор, а не строку. - person Maurice; 24.06.2018
comment
@Maurice для меня это работает: element.scrollIntoView() (без передачи element в функцию). Чтобы сделать его гладким, используйте это: element.scrollIntoView({block: "end", behavior: "smooth"}). - person Mr. B.; 16.07.2018
comment
Intellisense здесь показывает, что внутри onAnchorClick() мы должны передать логическое значение в scrollIntoView: if (element) { element.scrollIntoView(true); }. Теперь я могу дважды щелкнуть по одной и той же ссылке, и прокрутка работает - person Junior Mayhé; 29.08.2018

Ни один из предыдущих ответов не работал для меня. В последней попытке я попробовал в своем шаблоне:

<a (click)="onClick()">From Here</a>
<div id='foobar'>To Here</div>

С этим в моем .ts:

onClick(){
    let x = document.querySelector("#foobar");
    if (x){
        x.scrollIntoView();
    }
}

И это работает, как и ожидалось, для внутренних ссылок. На самом деле это не использует теги привязки, поэтому он вообще не будет касаться URL-адреса.

person cheese    schedule 09.11.2017
comment
просто и легко - person WasiF; 13.06.2019

Приведенные выше решения не сработали для меня... Это сделало это:

Сначала подготовьте MyAppComponent для автоматической прокрутки в ngAfterViewChecked()...

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 } );
  }

}
person JavierFuentes    schedule 02.06.2017
comment
Голосование против без комментариев или объяснений... это не очень хорошая практика... - person JavierFuentes; 09.06.2017
comment
Это сработало для меня! Зачем использовать ngAfterViewChecked вместо ngInit? - person Antoine Boisier-Michaud; 18.06.2017
comment
Спасибо @AntoineBoisier-Michaud за положительный отзыв. ngInit не всегда срабатывает в моем проекте... ngAfterViewChecked делает это. Можете ли вы проголосовать за это решение, пожалуйста? Спасибо. - person JavierFuentes; 18.06.2017

Все остальные ответы будут работать в версии Angular ‹ 6.1. Но если у вас последняя версия, вам не нужно делать эти уродливые хаки, поскольку Angular решил проблему.

вот ссылка на проблему

Все, что вам нужно сделать, это установить scrollOffset с опцией второго аргумента метода RouterModule.forRoot.

@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      scrollPositionRestoration: 'enabled',
      anchorScrolling: 'enabled',
      scrollOffset: [0, 64] // [x, y]
    })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}
person आनंद    schedule 28.08.2018
comment
будет ли это работать для внешних ссылок? скажем, с другого веб-сайта я нажимаю на www.abc.com#sectionToScrollTo - person Sushmit Sagar; 02.11.2018
comment
anchorScrolling не работает, если вы широко используете *ngIf, потому что он переходит к раннему :-( - person Jojo.Lechelt; 06.12.2018
comment
Единственная проблема, с которой я столкнулся, - это синхронизация - она ​​имеет тенденцию переходить к якорю до того, как стилизация какого-либо элемента достигнет полной визуализации, что приводит к отключению позиционирования. Было бы неплохо, если бы вы могли добавить задержку :) - person Charly; 13.02.2020

если не имеет значения, что эти идентификаторы элементов добавлены к URL-адресу, вам следует взглянуть на эту ссылку:

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
  }
 }

person Ramu N    schedule 05.09.2019

В 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();
  }
}
person Sebastian Schulze-Khyi    schedule 21.10.2019
comment
querySelector можно легко поместить в директиву с именем scrolllTo. URL-адрес будет следующим: ‹a scrollTo=test1 [routerLink]=['./']›Перейти к разделу «Тест 1»‹/a› - person JWP; 01.05.2020

Используйте это для модуля маршрутизатора в app-routing.module.ts:

@NgModule({
  imports: [RouterModule.forRoot(routes, {
    useHash: true,
    scrollPositionRestoration: 'enabled',
    anchorScrolling: 'enabled',
    scrollOffset: [0, 64]
  })],
  exports: [RouterModule]
})

Это будет в вашем HTML:

<a href="#/users/123#userInfo">
person faizal razak    schedule 13.12.2018

В дополнение к ответу Калояна, эта подписка привязана к маршрутизатору и будет действовать до тех пор, пока страница не будет полностью обновлена. При подписке на события маршрутизатора в компоненте обязательно отпишитесь в 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();
  }
}
person DBosley    schedule 20.07.2017
comment
Я думал, что подписки на маршрутные события автоматически срывались. - person ; 22.04.2018

Поскольку свойство фрагмента по-прежнему не обеспечивает прокрутку привязки, этот обходной путь помог мне:

<div [routerLink]="['somepath']" fragment="Test">
  <a href="#Test">Jump to 'Test' anchor </a>
</div>
person Martin Cremer    schedule 04.07.2017

Я только что заработал на своем собственном веб-сайте, поэтому решил, что стоит опубликовать здесь свое решение.

<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 )
     });
 }
person a_lovelace    schedule 27.07.2017
comment
Я думаю, что лучше писать просто element.scrollIntoView() или element.scrollIntoView(true). Ваша версия у меня не скомпилировалась (может быть из-за strictNullChecks?). - person David L.; 15.01.2018

Прочитав все решения, я искал компонент и нашел тот, который делает именно то, о чем задавался первоначальный вопрос: прокрутка до ссылок привязки. 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 {
}

Это сработало очень хорошо для меня.

person John    schedule 16.08.2017
comment
Используйте колесо, не изобретайте его снова ;) - person Yogen Rai; 11.11.2017
comment
Вы смотрели на код этого компонента? Это выглядит очень хрупким — в проекте также есть 14 открытых проблем, которые включают в себя такие вещи, как отсутствие элемента, нулевые цели, отсутствие прокрутки к элементу, проблемы с поддержкой браузера. - person Drenai; 24.01.2018
comment
не работает, когда у вас есть дочерний элемент (дочерний элемент имеет привязанные объекты и/или имена привязок) в родительском компоненте, он просто обновляет страницу - person Sasha Bond; 02.06.2018

Простое решение, которое работает для страниц без каких-либо параметров запроса, совместимо с браузером назад / вперед, маршрутизатором и глубокими ссылками.

<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. Это также можно использовать для прокрутки вверх страницы при изменении маршрута — просто укажите тег верхней привязки по умолчанию.

person Graham Hotchkiss    schedule 21.11.2017

В отличие от других ответов, я бы дополнительно добавил focus() вместе с scrollIntoView(). Также я использую setTimeout, так как в противном случае он переходит наверх при изменении URL-адреса. Не уверен, что послужило причиной этого, но кажется, что setTimeout делает обходной путь.

Источник:

<a [routerLink] fragment="some-id" (click)="scrollIntoView('some-id')">Jump</a>

Назначения:

<a id="some-id" tabindex="-1"></a>

Машинопись:

scrollIntoView(anchorHash) {
    setTimeout(() => {
        const anchor = document.getElementById(anchorHash);
        if (anchor) {
            anchor.focus();
            anchor.scrollIntoView();
        }
    });
}
person Hrvoje Golcic    schedule 25.09.2018

Вот еще один обходной путь со ссылкой на ответ 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-адресе.

Но в этом случае я подписал фрагмент маршрута в 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);
}
person Vicky Gonsalves    schedule 22.06.2017

Это работает для меня !! Этот 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>

Мой ТС-файл:

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 !!

person John Connor    schedule 04.09.2018

Я была такая же проблема. Решение: использование прокрутки порта просмотра 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);
      }

    }
person Abderrahim Taleb    schedule 28.08.2018

Я только что протестировал очень полезный плагин, доступный в nmp — ngx-scroll -to, который отлично работает для меня. Однако он предназначен для Angular 4+, но, возможно, кому-то этот ответ будет полезен.

person mpro    schedule 02.03.2018

Я попробовал большинство из этих решений, но столкнулся с проблемами при выходе и возвращении с другим фрагментом, это не сработало, поэтому я сделал что-то немного другое, что работает на 100% и избавился от уродливого хэша в URL-адресе.

tl; dr вот лучший способ, чем то, что я видел до сих пор.

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();
    }
}
person Kyle S    schedule 04.04.2018