Angular 4でクリックして要素にスクロールする


99

ボタンを押したときにターゲットまでスクロールできるようにしたい。このようなことを考えていました。

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

そして私の中でcomponent.tsのような方法。

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

上記のコードは有効ではありませんが、私が何を考えていたかを示すためだけのものです。Angularの経験がなく、Angular 4の学習を始めたばかりです。私はこのようなものを探していましたが、すべての例はAngularJにあり、Angular 4とはかなり異なります


1
構文には問題はありませんが、#targetを定義する必要があります。
wannadream

1
これはうまくいくでしょうか?任意の番号を使用して、関数でwindow.scrollTo(500)を呼び出しても何も起こりません。要素はHTMLElementだと思っていました

しかし、#targetとは何ですか、Angularはそれを解決しませんか?最初にパラメーターなしでscroll()をテストできます。
wannadream 2017年

はい、コンポーネントでボタンとwindow.scrollTo(

2
しかし、コンストラクタでwindow.scrollTo(

回答:


150

あなたはこのようにそれを行うことができます:

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

そしてあなたのコンポーネントで:

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

編集:要素が定義されていないため、これが機能しないことを示すコメントが表示されます。Angular 7でStackBlitzの例を作成しましたが、まだ動作します。それが機能しない例を誰かが提供できますか?


何らかの理由で、その正確なコードを実行しても何も起こりません。ハードコード化されたwindow.scrollTo(

1
@ N15M0_jkはい、必要に応じて、他のオプションで渡すことができるオブジェクトもあります。developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
Frank Modica

1
@Anthonyこれを使用するとscroll、コンポーネントの関数に渡す要素を参照できます。クリックイベントがを呼び出すことに注意してくださいscroll(target)。要素を渡さずにコンポーネント内から要素にアクセスしたい場合は、を使用できます@ViewChild
フランクモディカ2017

2
今では問題なく動作します。しかし、私が愚かな間違いをしてid="target"代わりに使用する前に#target、それは私に「el is undefined error」を与えました!
yashthakkar1173

1
私が持つ要素があれば、未定義のエラーが発生したと考えている#target内にある*ngIfが、あなたが使用している場合、それは動作するはず@ViewChild@abbastecからリンク方法を
spectacularbob

46

setTimeoutor requestAnimationFrameまたはjQuery を使用せずにこれを実現する純粋なJavaScriptの方法があります。

つまり、スクロール先のscrollViewで要素を見つけて、を使用しますscrollIntoView

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

こちらがプランカーです。


2
この答えが異なる2つの点:1.これはジャンプではなく、アニメーションのスムーズなスクロールです。2.この回答はウィンドウをスクロールしませんが、ウィンドウ内のスクロールビューを移動します。たとえば、ウィンドウ内に水平スクロールビューがある場合。例については、plunkrを確認してください。
Jon

1
scrollIntoViewのscrollIntoViewOptions(引数としてのオブジェクト)は、現時点ではFirefoxとのみ互換性があります。
ヘススフエンテス

ChromeとFirefoxでは正常に機能しますが、Safariでは機能しません。
山城リオン

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

テンプレートにelementRefまたはHTML IDを設定していません。スクロールしている 'cat-' + cat.category_id要素はどこに正確にありますか?
キーガン

1
これはより良い答えです。スクロールを別のコンポーネントに配置できます。
Dale Nguyen

これは受け入れられる答えになるはずです。角度9.のために働く
シックスティーン

30

Angular 7では完璧に機能します

HTML

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

コンポーネント内

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

2
{behavior: 'smooth'}のボーナス
Squaplレシピ

それは私のために働いています.. {behavior: 'smooth'}への特別な感謝
Vibhu kumar

これは#target、ボタンの後に定義されている場合は機能しません。たとえば、フローティングヘッダーがある場合に関連します...
Jonathan

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

私はフッターからヘッダーにスクロールバックしたかったので、この関数を配置するサービスを作成し、それをnavbarコンポーネントとフッターコンポーネントに挿入し、必要に応じて「ヘッダー」または「フッター」に渡しました。使用するクラス名をコンポーネント宣言に実際に与えることを忘れないでください。

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

15

Angularでそれを行う別の方法:

マークアップ:

<textarea #inputMessage></textarea>

ViewChild()プロパティを追加:

@ViewChild('inputMessage')
inputMessageRef: ElementRef;

scrollIntoView()関数を使用して、コンポーネント内の任意の場所にスクロールします。

this.inputMessageRef.nativeElement.scrollIntoView();

10

以下のコードブロックを使用して、ビューの任意の要素refにスクロールできます。ターゲット(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要素への参照を使用することで実現できます。

これが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>

6

角度では、使用することができますViewChildElementRef:あなたのHTML要素REFを与えます

<div #myDiv > 

コンポーネント内:

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

this.myDivRef.nativeElementあなたの要素に到達するために使用できます


これは良い解決策ですが、問題はタブをリロードしたときにのみ機能し、routerLinkでは機能しないことです。この問題の人のための解決策はありますか?
アーサン

-8

jQueryを使用して要素(などdocument.getElementById(...))を検索し、.focus()呼び出しを使用するだけで、あなたが求めているようなことを行いました。


3
Angularを使用する場合、jQueryは本当に必要ですか?角度のような感じでは十分なはずです

100%確かではありませんが、Angular2の検証とリファクタリングが行われていない環境にいたので、Angularのソリューションを探しすぎず、アクセスできることがわかっているものを使用しました。
ケネスサロモン

8
JqueryとAngularを使用しないでください
Stefdelec '28

2
はいはい、私は多くのことを学びました、そして誰もがjQueryを使うべきではないとコメントしました。他の人があなたの真上でコメントしていないことは何も言っていません。
ケネスサロモン

謙虚さのためにあなたを賛成した。私は、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
あなたは私のポイントを逃しました、あなたの答えは単にES *を使用するのではなく、jQueryを使用します(私は最も非効率的な方法で追加するかもしれません)。定数は型も宣言しません。これは、jQueryを使用した論理が不適切で、要求されたものではない、単なる悪い例です。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.