Прокрутіть до елемента після клацання в Angular 4


102

Я хочу мати можливість прокрутити до цілі при натисканні кнопки. Я думав приблизно так.

<button (click)="scroll(#target)">Button</button>

А в моєму component.tsтакий метод.

scroll(element) {
    window.scrollTo(element.yPosition)
}

Я знаю, що наведений вище код не дійсний, а лише для того, щоб показати, про що я думав. Я щойно почав вивчати Angular 4 без попереднього досвіду роботи з Angular. Я шукав щось подібне, але всі приклади знаходяться в AngularJs, що значно відрізняється від Angular 4


1
Ваш синтаксис не має проблем, але вам потрібно визначити, що таке #target.
wannadream

1
То це має спрацювати? Коли я використовую довільний номер і викликаю window.scrollTo (500) у моїй функції, нічого не відбувається. Я думав, що цим елементом буде HTMLElement

Правильно, однак, що таке #target, Angular не вирішить це? Ви можете спершу перевірити scroll () без параметра.
wannadream

Так, я спробував (клацнути) = "прокрутити ()" у своїй кнопці та вікні. ScrollTo (0, 500) у компоненті, але нічого не відбувається

2
Але коли я роблю window.scrollTo (0, 500) у конструкторі із затримкою 500 мс, це працює

Відповіді:


154

Ви можете зробити це так:

<button (click)="scroll(target)"></button>
<div #target>Your target</div>

а потім у вашому компоненті:

scroll(el: HTMLElement) {
    el.scrollIntoView();
}

Редагувати: я бачу коментарі про те, що це більше не працює, оскільки елемент не визначений. Я створив приклад StackBlitz в Angular 7, і він все ще працює. Чи може хтось навести приклад, коли це не працює?


З якоїсь причини запуск цього точного коду для мене нічого не робить. Навіть жорстко закодоване вікно. ScrollTo (0, 500) нічого не робить

1
@ N15M0_jk Так, є також об’єкт, куди можна передати інші варіанти, залежно від того, що вам потрібно. developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
Frank Modica

1
@Anthony Це дозволяє посилатися на елемент, який ви хочете передати scrollфункції на компоненті. Зверніть увагу, що викликається подія кліку scroll(target). Якщо ви хочете отримати доступ до елемента зсередини компонента без необхідності передавати елемент всередину, ви можете використовувати @ViewChild.
Frank Modica

2
Зараз це зі мною чудово працює. Але до того, як я зробив безглузду помилку і використав id="target"замість, #targetі це дало мені "el - невизначена помилка"!
yashthakkar1173

1
Я вважаю, що невизначена помилка трапляється, якщо елемент із символом #targetзнаходиться всередині *ngIf, але він повинен працювати, якщо ви використовуєте @ViewChildметод за посиланням від @abbastec
spectacularbob

46

Насправді існує чистий спосіб JavaScript для досягнення цього без використання setTimeoutабо requestAnimationFrameабо jQuery.

Коротше кажучи, знайдіть елемент у scrollView, до якого ви хочете прокрутити та використати scrollIntoView.

el.scrollIntoView({behavior:"smooth"});

Ось плюнкр .


2
2 способи відмінність цієї відповіді: 1. Це анімоване плавне прокручування, а не стрибок. 2. Ця відповідь не прокручує вікно, а переміщує прокрутку всередині вікна. Наприклад, якщо у вас є горизонтальне прокручування у вікні. Перевірте plunkr для прикладу.
Джон

1
scrollIntoView scrollIntoViewOptions (об'єкт як аргумент) зараз сумісний лише з Firefox.
Хесус Фуентес

Чудово працює для Chrome та Firefox, але не для Safari.
Yamashiro Rion

45

Ось як я це зробив за допомогою Angular 4.

Шаблон

<div class="col-xs-12 col-md-3">
  <h2>Categories</h2>
  <div class="cat-list-body">
    <div class="cat-item" *ngFor="let cat of web.menu | async">
      <label (click)="scroll('cat-'+cat.category_id)">{{cat.category_name}}</label>
    </div>
  </div>
</div>

додати цю функцію до компонента.

scroll(id) {
  console.log(`scrolling to ${id}`);
  let el = document.getElementById(id);
  el.scrollIntoView();
}

Ви не встановили ідентифікатори elementRefs або HTML у своєму шаблоні. Де саме знаходиться елемент 'cat -' + cat.category_id, до якого ви прокручуєте?
Кіган,

1
Це краща відповідь. Ви можете помістити прокрутку до іншого компонента.
Дейл Нгуєн

Це має бути прийнятою відповіддю. Працюємо на Angular 9.
Шістнадцять

33

У Angular 7 працює ідеально

HTML

<button (click)="scroll(target)">Click to scroll</button>
<div #target>Your target</div>

В компоненті

  scroll(el: HTMLElement) {
    el.scrollIntoView({behavior: 'smooth'});
  }

2
бонус за {поведінку: 'гладкий'}
Squapl Recipes

Це працює для мене .. особлива подяка за {поведінку: 'smooth'}
Vibhu kumar

Це не спрацює, якщо #targetце визначено після кнопки, що актуально, якщо у вас, наприклад, є плаваючий заголовок ...
Джонатан,

21

Джон має правильну відповідь, і це працює в моїх кутових 5 і 6 проектах.

Якщо я хотів натиснути, щоб плавно перейти від навігаційної панелі до нижнього колонтитула:

<button (click)="scrollTo('.footer')">ScrolltoFooter</button>
<footer class="footer">some code</footer>

scrollTo(className: string):void {
   const elementList = document.querySelectorAll('.' + className);
   const element = elementList[0] as HTMLElement;
   element.scrollIntoView({ behavior: 'smooth' });
}

Оскільки я хотів прокрутити назад до верхнього колонтитула з нижнього колонтитула, я створив службу, в якій знаходиться ця функція, і ввів її в компоненти панелі навігації та нижнього колонтитула і передав там, де потрібно, „верхній колонтитул” або „нижній колонтитул”. просто пам’ятайте, що насправді потрібно давати оголошенням компонентів використовувані імена класів:

<app-footer class="footer"></app-footer>

15

Інший спосіб зробити це в Angular:

Розмітка:

<textarea #inputMessage></textarea>

Додати ViewChild()властивість:

@ViewChild('inputMessage')
inputMessageRef: ElementRef;

Прокрутіть де завгодно всередині компонента за допомогою scrollIntoView()функції:

this.inputMessageRef.nativeElement.scrollIntoView();

10

Ви можете перейти до будь-якого елемента ref у своєму поданні, використовуючи блок коду нижче. Зверніть увагу, що target (elementref id ) може бути на будь-якому дійсному тегу html.

У поданні (файл HTML)

<div id="target"> </div>
<button (click)="scroll()">Button</button>
 

  

на .ts файлі,

scroll() {
   document.querySelector('#target').scrollIntoView({ behavior: 'smooth', block: 'center' });
}

7

Ви можете досягти цього, використовуючи посилання на кутовий елемент DOM наступним чином:

Ось приклад у стек-бліці

шаблон компонента:

<div class="other-content">
      Other content
      <button (click)="element.scrollIntoView({ behavior: 'smooth', block: 'center' })">
        Click to scroll
      </button>
    </div>
    <div id="content" #element>
      Some text to scroll
</div>

6

В Angular ви можете використовувати ViewChildі ElementRef: дайте елементу HTML посилання

<div #myDiv > 

і всередині вашого компонента:

import { ViewChild, ElementRef } from '@angular/core';
@ViewChild('myDiv') myDivRef: ElementRef;

ви можете використовувати, this.myDivRef.nativeElementщоб дістатися до вашого елемента


Це хороше рішення, але проблема в тому, що воно працює лише тоді, коли я перезавантажую вкладку, але не з routerLink. Будь-яке рішення цієї проблеми, хлопці?
Ahsan

-8

Я зробив щось на зразок того, що ви запитуєте, просто використовуючи jQuery для пошуку елемента (наприклад document.getElementById(...)) та використовуючи .focus()виклик.


3
Чи справді потрібен jQuery при використанні Angular? Відчуття, як Angular, повинно бути достатньо

Не впевнений на 100%, але я опинився в середовищі, яке не було перевірено та перероблено для Angular2, тому я не надто шукав рішення в Angular, а просто пішов із чимось, до чого я знав, що маю доступ.
Кеннет Саломон,

8
Ви не повинні використовувати Jquery та Angular
Stefdelec

2
Так так, я багато чому навчився, і всі коментують, що я не повинен користуватися jQuery. Ви не говорите нічого, що інші не коментували прямо над вами.
Кеннет Саломон,

Проголосував за смирення. Я хотів би додати, що відповіді jQuery мають певне значення для тих, хто переходить до фреймворків SPA. Показавши, як ми це робили раніше, і побачивши коментарі, що рекомендують інші рішення.
B2K

-17

Ви можете зробити це за допомогою jquery:

код коду:

    scrollTOElement = (element, offsetParam?, speedParam?) => {
    const toElement = $(element);
    const focusElement = $(element);
    const offset = offsetParam * 1 || 200;
    const speed = speedParam * 1 || 500;
    $('html, body').animate({
      scrollTop: toElement.offset().top + offset
    }, speed);
    if (focusElement) {
      $(focusElement).focus();
    }
  }

html код:

<button (click)="scrollTOElement('#elementTo',500,3000)">Scroll</button>

Застосуйте це до елементів, які потрібно прокрутити:

<div id="elementTo">some content</div>

Ось зразок стек-бліц.


1
За винятком того, що ця операційна система вимагає, щоб рішення TypeScript не працювали навколо із застарілим фреймворком (голосування проти)
ash

це рішення машинопису.
Gns

1
Ви пропустили мою думку, ваша відповідь використовує jQuery (можна додати найбільш неефективним способом), а не просто використовуючи ES *. Ваші константи також не оголошують свій тип. Це просто поганий приклад з поганою логікою за допомогою jQuery, який не є тим, про що запитували.
попіл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.