Scorri fino all'elemento facendo clic in Angular 4


99

Voglio essere in grado di scorrere fino a una destinazione quando viene premuto un pulsante. Stavo pensando qualcosa del genere.

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

E nel mio component.tsun metodo simile.

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

So che il codice sopra non è valido ma solo per mostrare cosa stavo pensando. Ho appena iniziato a imparare Angular 4 senza alcuna precedente esperienza di Angular. Ho cercato qualcosa del genere, ma tutti gli esempi sono in AngularJs che differisce molto da Angular 4


1
La tua sintassi non ha problemi ma devi definire cosa è #target.
wannadream

1
Quindi questo dovrebbe funzionare? Quando utilizzo un numero arbitrario e chiamo window.scrollTo (500) nella mia funzione non succede nulla. Stavo pensando che l'elemento sarebbe un HTMLElement

Giusto, però, cos'è #target, Angular non lo risolverà? Puoi prima provare scroll () senza alcun parametro.
wannadream

Sì, ho provato (click) = "scroll ()" nel mio pulsante e window.scrollTo (0, 500) nel componente ma non succede nulla

2
Ma quando eseguo window.scrollTo (0, 500) nel costruttore con un ritardo di 500 ms, funziona

Risposte:


150

Potresti farlo in questo modo:

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

e poi nel tuo componente:

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

Modifica: vedo commenti che affermano che questo non funziona più perché l'elemento non è definito. Ho creato un esempio StackBlitz in Angular 7 e funziona ancora. Qualcuno può fornire un esempio in cui non funziona?


Per qualche motivo l'esecuzione di quel codice esatto non fa nulla per me. Anche una finestra hardcoded.scrollTo (0, 500) non fa nulla

1
@ N15M0_jk Sì, c'è anche un oggetto che puoi passare con altre opzioni, a seconda di ciò che ti serve. developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
Frank Modica

1
@Anthony Consente di fare riferimento all'elemento che si desidera passare alla scrollfunzione sul componente. Notare che l'evento di clic chiama scroll(target). Se si desidera accedere all'elemento dall'interno del componente senza dover passare l'elemento, è possibile utilizzare @ViewChild.
Frank Modica

2
Ora funziona bene con me. Ma prima ho fatto uno stupido errore e ho usato id="target"invece di #targete mi ha dato "el è un errore indefinito"!
yashthakkar1173

1
Credo che l'errore indefinito si verifichi se l'elemento con #targetè all'interno di un *ngIf, ma dovrebbe funzionare se usi il @ViewChildmetodo nel link da @abbastec
spettacolarebob

46

In realtà esiste un modo javascript puro per farlo senza utilizzare setTimeoutor requestAnimationFrameor jQuery.

In breve, trova l'elemento in scrollView che desideri scorrere e usa scrollIntoView.

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

Ecco un plunkr .


2
2 modi in cui questa risposta è diversa: 1. Questo è uno scorrimento fluido animato, non un salto. 2. Questa risposta non fa scorrere una finestra, ma sposta una scrollview all'interno di una finestra. Ad esempio, se hai una visualizzazione a scorrimento orizzontale all'interno della finestra. Controlla il plunkr per un esempio.
Jon

1
scrollIntoView's scrollIntoViewOptions (l'oggetto come argomento) è compatibile solo con Firefox in questo momento.
Jesús Fuentes

Funziona bene per Chrome e Firefox, ma non per Safari.
Yamashiro Rion

45

Ecco come l'ho fatto usando Angular 4.

Modello

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

aggiungere questa funzione al componente.

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

Non hai impostato elementRefs o HTML id nel tuo modello. Dove si trova esattamente l'elemento "cat -" + cat.category_id su cui stai scorrendo?
Keegan

1
Questa è una risposta migliore. Puoi mettere la pergamena su un altro componente.
Dale Nguyen

Questa dovrebbe essere la risposta accettata. Lavorare per Angular 9.
Sedici

30

In Angular 7 funziona perfettamente

HTML

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

In componente

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

2
bonus per {behavior: 'smooth'}
Squapl Recipes

Per me sta funzionando .. un ringraziamento speciale per {behavior: 'smooth'}
Vibhu kumar

Questo non funzionerà se #targetè definito dopo il pulsante, che è rilevante se hai un'intestazione mobile, ad esempio ...
Jonathan

21

Jon ha la risposta giusta e questo funziona nei miei progetti angolari 5 e 6.

Se volessi fare clic per scorrere senza problemi dalla barra di navigazione al piè di pagina:

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

Poiché volevo tornare all'intestazione dal piè di pagina, ho creato un servizio in cui si trova questa funzione e l'ho inserito nei componenti della barra di navigazione e del piè di pagina e passato in "intestazione" o "piè di pagina" dove necessario. ricorda solo di dare effettivamente alle dichiarazioni dei componenti i nomi delle classi utilizzate:

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

15

Un altro modo per farlo in Angular:

Markup:

<textarea #inputMessage></textarea>

Aggiungi ViewChild()proprietà:

@ViewChild('inputMessage')
inputMessageRef: ElementRef;

Scorri dove vuoi all'interno del componente usando la scrollIntoView()funzione:

this.inputMessageRef.nativeElement.scrollIntoView();

10

Puoi scorrere fino a qualsiasi elemento di riferimento nella tua vista utilizzando il blocco di codice di seguito. Nota che il target (elementref id ) potrebbe essere su qualsiasi tag html valido.

Nella vista (file html)

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

  

sul .tsfile,

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

7

Puoi ottenerlo utilizzando il riferimento a un elemento DOM angolare come segue:

Ecco l'esempio in stackblitz

il modello del componente:

<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

In Angular puoi usare ViewChilde ElementRef: dai al tuo elemento HTML un riferimento

<div #myDiv > 

e all'interno del tuo componente:

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

puoi usare this.myDivRef.nativeElementper arrivare al tuo elemento


Questa è una buona soluzione, ma il problema è che funziona solo quando ricarico la scheda ma non con routerLink. Qualche soluzione per questo problema ragazzi?
Ahsan

-8

Ho fatto qualcosa di simile a quello che stai chiedendo semplicemente usando jQuery per trovare l'elemento (come document.getElementById(...)) e usando la .focus()chiamata.


3
JQuery è davvero necessario quando si utilizza Angular? Sembra che Angular dovrebbe essere sufficiente

Non sono sicuro al 100% ma mi trovavo in un ambiente che non è stato convalidato e refactoring per Angular2, quindi non ho cercato troppo a fondo una soluzione in Angular e sono andato con qualcosa a cui sapevo avrei avuto accesso.
Kenneth Salomon

8
Non dovresti usare Jquery e Angular
Stefdelec

2
Sì sì, ho imparato molto e tutti commentano che non dovrei usare jQuery. Non stai dicendo nulla che gli altri non abbiano commentato proprio sopra di te.
Kenneth Salomon

Ti ho votato per l'umiltà. Vorrei aggiungere che le risposte jQuery hanno un certo valore per coloro che stanno passando ai framework SPA. Mostrando come lo facevamo e vedendo i commenti che consigliavano altre soluzioni.
B2K

-17

Puoi farlo usando jquery:

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

codice html:

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

Applicalo sugli elementi che vuoi scorrere:

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

Ecco un esempio di stackblitz.


1
Tranne che questa operazione richiede che le soluzioni TypeScript non funzionino con un framework obsoleto (votato verso il basso)
ash

questa è una soluzione dattiloscritta.
Gns

1
Hai perso il mio punto, la tua risposta usa jQuery (potrei aggiungere nel modo più inefficiente) piuttosto che semplicemente usando ES *. Le tue costanti non dichiarano nemmeno il loro tipo. È solo un cattivo esempio con una cattiva logica che utilizza jQuery che non è ciò che è stato chiesto.
cenere
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.