เลื่อนไปที่องค์ประกอบเมื่อคลิกใน Angular 4


115

ฉันต้องการเลื่อนไปยังเป้าหมายเมื่อกดปุ่ม ฉันกำลังคิดอะไรแบบนี้

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

และในcomponent.tsวิธีการของฉันเช่น

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

ฉันรู้ว่ารหัสด้านบนไม่ถูกต้อง แต่เพียงเพื่อแสดงสิ่งที่ฉันคิด ฉันเพิ่งเริ่มเรียนรู้ Angular 4 โดยไม่มีประสบการณ์ Angular มาก่อน ฉันค้นหาอะไรทำนองนี้มาตลอด แต่ตัวอย่างทั้งหมดอยู่ใน AngularJs ซึ่งแตกต่างจาก Angular 4 มาก


1
ไวยากรณ์ของคุณไม่มีปัญหา แต่คุณต้องกำหนดว่าอะไรคือ # เป้าหมาย
wannadream

1
ดังนั้นควรใช้งานได้หรือไม่? เมื่อฉันใช้หมายเลขตามอำเภอใจและเรียก window.scrollTo (500) ในฟังก์ชันของฉันจะไม่มีอะไรเกิดขึ้น ฉันคิดว่าองค์ประกอบนั้นน่าจะเป็น HTMLElement

อย่างไรก็ตาม # เป้าหมายคืออะไร Angular จะไม่สามารถแก้ไขได้ คุณสามารถทดสอบ scroll () โดยไม่มีพารามิเตอร์ก่อน
wannadream

ใช่ฉันพยายาม (คลิก) = "scroll ()" ในปุ่มและ window.scrollTo (0, 500) ในส่วนประกอบ แต่ไม่มีอะไรเกิดขึ้น

2
แต่เมื่อฉันทำ window.scrollTo (0, 500) ในตัวสร้างด้วยความล่าช้า 500ms มันใช้งานได้

คำตอบ:


163

คุณสามารถทำได้ดังนี้:

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

จากนั้นในส่วนประกอบของคุณ:

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

แก้ไข:ฉันเห็นความคิดเห็นที่ระบุว่าสิ่งนี้ใช้ไม่ได้อีกต่อไปเนื่องจากองค์ประกอบไม่ได้กำหนดไว้ ฉันสร้างตัวอย่าง StackBlitzใน Angular 7 และยังใช้งานได้ ใครช่วยยกตัวอย่างที่มันใช้ไม่ได้


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 is undefined error"!
yashthakkar1173

1
ผมเชื่อว่าข้อผิดพลาดที่เกิดขึ้นถ้าไม่ได้กำหนดองค์ประกอบที่มีความ#targetเป็นอยู่ภายใน*ngIfแต่มันควรจะทำงานถ้าคุณใช้@ViewChildวิธีการในการเชื่อมโยงจาก @abbastec
spectacularbob

1
เรียบง่ายและเรียบร้อย ใช้ได้ผลกับฉันใน Angular 10
griffinleow

55

นี่คือวิธีที่ฉันใช้ 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();
}

1
คุณยังไม่ได้ตั้งค่า elementRefs หรือ HTML id ในเทมเพลตของคุณ องค์ประกอบ 'cat -' + cat.category_id ที่คุณเลื่อนไปอยู่ที่ไหนกันแน่?
Keegan

1
นี่คือคำตอบที่ดีกว่า คุณสามารถเลื่อนไปยังส่วนประกอบอื่นได้
Dale Nguyen

1
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ ทำงานให้กับ Angular 9.
สิบหก

51

มีวิธี javascript ที่บริสุทธิ์ในการทำสิ่งนี้โดยไม่ใช้setTimeoutหรือrequestAnimationFrameหรือ jQuery

ในระยะสั้นหาองค์ประกอบใน scrollview scrollIntoViewที่คุณต้องการเพื่อเลื่อนไปและการใช้งาน

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

นี่คือplunkr


3
คำตอบนี้แตกต่างกัน 2 วิธี: 1. นี่คือการเลื่อนแบบเคลื่อนไหวได้อย่างราบรื่นไม่ใช่การกระโดด 2. คำตอบนี้ไม่ได้เลื่อนหน้าต่าง แต่จะย้ายมุมมองแบบเลื่อนภายในหน้าต่าง ตัวอย่างเช่นหากคุณมีภาพเลื่อนแนวนอนภายในหน้าต่าง ตรวจสอบ plunkr เป็นตัวอย่าง
จอน

1
scrollIntoViewOptions ของ scrollIntoView (อ็อบเจ็กต์เป็นอาร์กิวเมนต์) เข้ากันได้กับ Firefox เท่านั้นในขณะนี้
Jesús Fuentes

ใช้งานได้ดีสำหรับ Chrome และ Firefox แต่ไม่ใช่สำหรับ Safari
Yamashiro Rion

41

ใน Angular 7 ทำงานได้อย่างสมบูรณ์แบบ

HTML

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

ในส่วนประกอบ

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

2
โบนัสสำหรับ {พฤติกรรม: 'smooth'}
Squapl Recipes

มันใช้ได้ผลสำหรับฉัน .. ขอบคุณเป็นพิเศษสำหรับ {พฤติกรรม: 'smooth'}
Vibhu kumar

1
สิ่งนี้จะไม่ทำงานหาก#targetกำหนดไว้หลังปุ่มซึ่งเกี่ยวข้องหากคุณมีส่วนหัวแบบลอยเช่น ...
Jonathan

22

จอนมีคำตอบที่ถูกต้องและใช้งานได้ในโครงการเชิงมุม 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();

12

คุณสามารถเลื่อนไปที่องค์ประกอบอ้างอิงในมุมมองของคุณได้โดยใช้บล็อกโค้ดด้านล่าง โปรดทราบว่าเป้าหมาย(id elementref ) อาจอยู่บนแท็ก html ที่ถูกต้อง

ในมุมมอง (ไฟล์ html)

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

  

ใน.tsไฟล์

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

7

คุณสามารถบรรลุได้โดยใช้การอ้างอิงถึงองค์ประกอบ DOM เชิงมุมดังต่อไปนี้:

นี่คือตัวอย่างในstackblitz

แม่แบบส่วนประกอบ:

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

7

ใน Angular คุณสามารถใช้ViewChildและElementRef: ให้องค์ประกอบ HTML ของคุณอ้างอิง

<div #myDiv > 

และภายในส่วนประกอบของคุณ:

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

คุณสามารถใช้this.myDivRef.nativeElementเพื่อไปยังองค์ประกอบของคุณ


นี่เป็นวิธีแก้ปัญหาที่ดี แต่ปัญหาคือจะใช้ได้เฉพาะเมื่อฉันโหลดแท็บใหม่ แต่ไม่สามารถใช้กับ routerLink ได้ มีทางออกสำหรับปัญหานี้ไหม
Ahsan

ฉันจะใช้ a classกับสิ่งนี้ได้อย่างไร
C Alonso C Ortega

0

ฉันต้องทำเคล็ดลับนี้อาจเป็นเพราะฉันใช้องค์ประกอบ HTML ที่กำหนดเอง ถ้าฉันไม่ทำเช่นนี้ targetในonItemAmounterClickจะไม่ได้มีscrollIntoViewวิธีการ

.html

<div *ngFor"...">
      <my-component #target (click)="clicked(target)"></my-component>
</div>

.ts

onItemAmounterClick(target){
  target.__ngContext__[0].scrollIntoView({behavior: 'smooth'});
}

-8

ฉันได้ทำบางสิ่งบางอย่างเช่นสิ่งที่คุณต้องการเพียงแค่ใช้ jQuery เพื่อค้นหาองค์ประกอบ (เช่นdocument.getElementById(...)) และใช้การ.focus()โทร


3
jQuery จำเป็นจริงๆหรือไม่เมื่อใช้ Angular? รู้สึกเหมือน Angular น่าจะเพียงพอ

ไม่แน่ใจ 100% แต่ฉันอยู่ในสภาพแวดล้อมที่ไม่ได้รับการตรวจสอบและปรับโครงสร้างใหม่สำหรับ Angular2 ดังนั้นฉันจึงไม่ได้ค้นหาวิธีแก้ปัญหาใน Angular ยากเกินไปและเพิ่งไปกับบางสิ่งที่ฉันรู้ว่าฉันจะเข้าถึงได้
Kenneth Salomon

8
คุณไม่ควรใช้ Jquery และ Angular
Stefdelec

2
ใช่ฉันได้เรียนรู้มากมายและทุกคนแสดงความคิดเห็นว่าฉันไม่ควรใช้ jQuery คุณไม่ได้พูดอะไรที่คนอื่นไม่ได้แสดงความคิดเห็นเหนือคุณ
Kenneth Salomon

โหวตให้คุณสำหรับความอ่อนน้อมถ่อมตน ฉันต้องการเพิ่มว่าคำตอบของ jQuery มีคุณค่าสำหรับผู้ที่กำลังเปลี่ยนไปใช้กรอบงาน SPA โดยแสดงวิธีที่เราเคยทำและดูความคิดเห็นที่แนะนำวิธีแก้ปัญหาอื่น ๆ
B2K

-17

คุณสามารถทำได้โดยใช้ jquery:

รหัส 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();
    }
  }

รหัส html:

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

ใช้สิ่งนี้กับองค์ประกอบที่คุณต้องการเลื่อน:

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

นี่คือตัวอย่าง stackblitz


1
ยกเว้นหน่วยงานนี้กำลังขอโซลูชัน TypeScript ไม่สามารถแก้ไขได้ด้วยกรอบงานที่ล้าสมัย (โหวตลง)
Ash

นี่คือโซลูชัน typescript
Gns

1
คุณพลาดประเด็นของฉันไปแล้วคำตอบของคุณใช้ jQuery (ฉันขอเพิ่มด้วยวิธีที่ไม่มีประสิทธิภาพที่สุด) แทนที่จะใช้ ES * ค่าคงที่ของคุณไม่ได้ประกาศประเภทของพวกมัน เป็นเพียงตัวอย่างที่ไม่ดีด้วยตรรกะที่ไม่ดีโดยใช้ jQuery ซึ่งไม่ใช่สิ่งที่ถูกถาม
เถ้า
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.