Cuộn đến phần tử khi nhấp trong Angular 4


99

Tôi muốn có thể cuộn đến mục tiêu khi nhấn một nút. Tôi đã nghĩ một cái gì đó như thế này.

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

Và trong component.tsmột phương pháp của tôi như thế nào.

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

Tôi biết rằng đoạn mã trên không hợp lệ nhưng chỉ để hiển thị những gì tôi đang nghĩ. Tôi mới bắt đầu tìm hiểu Angular 4 mà chưa có kinh nghiệm về Angular. Tôi đã tìm kiếm xung quanh một cái gì đó như thế này nhưng tất cả các ví dụ đều có trong AngularJs, khác với Angular 4


1
Cú pháp của bạn không có vấn đề nhưng bạn cần xác định # mục tiêu là gì.
wannadream

1
Vì vậy, điều này nên làm việc? Khi tôi sử dụng một số tùy ý và gọi window.scrollTo (500) trong hàm của tôi, không có gì xảy ra. Tôi đang nghĩ phần tử đó sẽ là HTMLElement

Đúng, tuy nhiên, #target là gì, Angular sẽ không giải quyết được nó? Trước tiên, bạn có thể kiểm tra scroll () không có tham số.
wannadream

Vâng, tôi đã thử (click) = "scroll ()" trong nút của mình và window.scrollTo (0, 500) trong thành phần nhưng không có gì xảy ra

2
Nhưng khi tôi thực hiện window.scrollTo (0, 500) trong hàm tạo với độ trễ 500ms thì nó hoạt động

Câu trả lời:


150

Bạn có thể làm như thế này:

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

và sau đó trong thành phần của bạn:

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

Chỉnh sửa: Tôi thấy các bình luận nói rằng điều này không còn hoạt động do phần tử không được xác định. Tôi đã tạo một ví dụ về StackBlitz trong Angular 7 và nó vẫn hoạt động. Ai đó có thể vui lòng cung cấp một ví dụ nơi nó không hoạt động không?


Vì lý do nào đó, việc chạy mã chính xác đó không làm được gì cho tôi. Ngay cả một window.scrollTo hardcoded (0, 500) không có gì

1
@ N15M0_jk Đúng, cũng có một đối tượng mà bạn có thể chuyển vào với các tùy chọn khác, tùy thuộc vào những gì bạn cần. developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
Frank Modica

1
@Anthony Nó cho phép bạn tham chiếu phần tử mà bạn muốn chuyển tới scrollhàm trên thành phần. Lưu ý rằng sự kiện nhấp chuột gọi scroll(target). Nếu bạn muốn có quyền truy cập vào phần tử từ bên trong thành phần mà không cần phải chuyển phần tử vào, bạn có thể sử dụng @ViewChild.
Frank Modica,

2
Nó hoạt động tốt với tôi bây giờ. Nhưng trước khi tôi mắc một sai lầm ngớ ngẩn và sử dụng id="target"thay vì #targetvà nó cho tôi "el là lỗi không xác định"!
yashthakkar1173

1
Tôi tin rằng lỗi không xác định xảy ra nếu phần tử có dấu #targetnằm bên trong một *ngIf, nhưng nó sẽ hoạt động nếu bạn sử dụng @ViewChildphương pháp trong liên kết từ @abbastec
ngoạn mục

46

Thực tế có một cách javascript thuần túy để thực hiện điều này mà không cần sử dụng setTimeouthoặc requestAnimationFramehoặc jQuery.

Tóm lại, hãy tìm phần tử trong scrollView mà bạn muốn cuộn đến và sử dụng scrollIntoView.

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

Đây là một plunkr .


2
Có 2 cách mà câu trả lời này khác nhau: 1. Đây là hoạt động cuộn mượt mà, không phải là một bước nhảy. 2. Câu trả lời này không di chuyển một cửa sổ, nhưng di chuyển một chế độ xem cuộn trong một cửa sổ. Ví dụ: nếu bạn có chế độ xem cuộn ngang trong cửa sổ. Kiểm tra plunkr cho một ví dụ.
Jon

1
scrollIntoViewOptions của scrollIntoView (đối tượng là đối số) hiện chỉ tương thích với Firefox.
Jesús Fuentes

Hoạt động tốt với Chrome và Firefox, nhưng không hoạt động với Safari.
Yamashiro Rion

45

Đây là cách tôi đã làm điều đó bằng cách sử dụng Angular 4.

Bản mẫu

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

thêm chức năng này vào Thành phần.

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

Bạn chưa đặt elementRefs hoặc HTML id trong mẫu của mình. Chính xác thì phần tử 'cat -' + cat.category_id mà bạn đang cuộn đến ở đâu?
Keegan

1
Đây là một câu trả lời tốt hơn. Bạn có thể đặt cuộn sang một thành phần khác.
Dale Nguyen

Đây phải là câu trả lời được chấp nhận. Làm việc cho Angular 9.
16

30

Trong Angular 7 hoạt động hoàn hảo

HTML

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

Trong thành phần

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

2
tiền thưởng cho {hành vi: 'mịn'}
Squapl Recipes

Nó đang làm việc cho tôi .. đặc biệt cảm ơn vì {hành vi: 'mịn'}
Vibhu kumar

Điều này sẽ không hoạt động nếu #targetđược xác định sau nút, có liên quan nếu bạn có tiêu đề nổi chẳng hạn ...
Jonathan

21

Jon có câu trả lời đúng và điều này hoạt động trong các dự án góc 5 và 6 của tôi.

Nếu tôi muốn nhấp để cuộn trơn tru từ thanh điều hướng đến chân trang:

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

Vì tôi muốn cuộn trở lại đầu trang từ chân trang, tôi đã tạo một dịch vụ có chức năng này nằm trong đó và đưa nó vào các thành phần thanh điều hướng và chân trang và chuyển vào 'đầu trang' hoặc 'chân trang' nếu cần. chỉ cần nhớ thực sự cung cấp cho các khai báo thành phần tên lớp được sử dụng:

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

15

Một cách khác để làm điều đó trong Angular:

Đánh dấu:

<textarea #inputMessage></textarea>

Thêm thuộc ViewChild()tính:

@ViewChild('inputMessage')
inputMessageRef: ElementRef;

Cuộn đến bất cứ nơi nào bạn muốn bên trong thành phần bằng cách sử dụng scrollIntoView()hàm:

this.inputMessageRef.nativeElement.scrollIntoView();

10

Bạn có thể cuộn đến bất kỳ tham chiếu phần tử nào trên chế độ xem của mình bằng cách sử dụng khối mã bên dưới. Lưu ý rằng đích (id phần tửref ) có thể nằm trên bất kỳ thẻ html hợp lệ nào.

Trên chế độ xem (tệp html)

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

  

trên .tshồ sơ,

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

7

Bạn có thể đạt được điều đó bằng cách sử dụng tham chiếu đến phần tử DOM góc cạnh như sau:

Đây là ví dụ trong stackblitz

mẫu thành phần:

<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

Trong Angular, bạn có thể sử dụng ViewChildElementRef: cung cấp cho phần tử HTML của bạn một tham chiếu

<div #myDiv > 

và bên trong thành phần của bạn:

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

bạn có thể sử dụng this.myDivRef.nativeElementđể đến phần tử của mình


Đây là một giải pháp tốt nhưng vấn đề là nó chỉ hoạt động khi tôi tải lại tab chứ không phải với routerLink. Bất kỳ giải pháp cho vấn đề này guys?
Ahsan

-8

Tôi đã làm điều gì đó giống như những gì bạn yêu cầu chỉ bằng cách sử dụng jQuery để tìm phần tử (chẳng hạn như document.getElementById(...)) và sử dụng lệnh .focus()gọi.


3
JQuery có thực sự cần thiết khi sử dụng Angular không? Cảm thấy như Angular là đủ

Không chắc chắn 100% nhưng tôi đang ở trong một môi trường chưa được xác thực và cấu trúc lại cho Angular2 vì vậy tôi không quá vất vả tìm kiếm giải pháp trong Angular và chỉ tìm kiếm một thứ mà tôi biết mình sẽ có quyền truy cập.
Kenneth Salomon

8
Bạn không nên sử dụng Jquery và góc
Stefdelec

2
Vâng vâng, tôi đã học được rất nhiều và mọi người đều nhận xét rằng tôi không nên sử dụng jQuery. Bạn không nói bất cứ điều gì mà người khác chưa nhận xét ngay trên bạn.
Kenneth Salomon

Đã ủng hộ bạn vì sự khiêm tốn. Tôi muốn thêm rằng các câu trả lời jQuery có một số giá trị đối với những câu trả lời đang chuyển sang các khuôn khổ SPA. Bằng cách hiển thị cách chúng tôi đã sử dụng để làm điều đó và xem các nhận xét đề xuất các giải pháp khác.
B2K

-17

Bạn có thể làm điều này bằng cách sử dụng jquery:

mã ts:

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

Mã HTML :

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

Áp dụng điều này trên các phần tử bạn muốn cuộn:

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

Đây là một mẫu stackblitz.


1
Trừ op này là yêu cầu cho các giải pháp nguyên cảo không ở quanh làm việc với một khuôn khổ lỗi thời (giảm bình chọn)
tro

đây là giải pháp sắp chữ.
Gns

1
Bạn đã bỏ lỡ quan điểm của tôi, câu trả lời của bạn sử dụng jQuery (tôi có thể thêm vào theo cách kém hiệu quả nhất) thay vì chỉ sử dụng ES *. Các hằng của bạn cũng không khai báo kiểu của chúng. Đó chỉ là một ví dụ tồi với logic tồi bằng cách sử dụng jQuery mà không phải là những gì được yêu cầu.
ash,
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.