web-dev-qa-db-ja.com

Angular ui-routerはui-viewではなく上にスクロールします

_ui-router 0.2.8_から_0.2.0_にアップグレードしたばかりで、状態が変わると、スクロール位置が新しい子の対象である_ui-view_の先頭にジャンプすることに気付きました状態。

これは問題ありませんが、2つの問題があります。

1)ページの上部と_ui-view_の間に30pxのパディングがあり、ギャップを残してページの上部までスクロールしたい。現時点では、それは_ui-view_の最上部に正確に移動し、見苦しくなります。これを達成するには、UIビューが存在するdivの上部(ブラウザviewportではない)にスクロールする方法を知る必要があるか、オーバーライドする方法を見つける必要があると思います_$uiViewScroll_は、_ui-view_から30pxを引いてスクロールします。

$uiViewScrollProvider.useAnchorScroll();を試しましたが、それを行ってもまったくスクロールしません。スクロールを完全に停止する_<ui-view autoscroll="false">;_も試しました。

2)現時点では実際にはスクロールせず、ジャンプするだけです。スクロールすることを想定していますか、それともCSSトランジションでこれを行うのは開発者次第ですか?

どんな助けも本当に感謝されます:)

64
jonhobbs

別のアプローチは、デフォルトの$uiViewScrollサービス。デフォルトの動作を効果的にオーバーライドします。

app.config(function ($provide) {
  $provide.decorator('$uiViewScroll', function ($delegate) {
    return function (uiViewElement) {
      // var top = uiViewElement.getBoundingClientRect().top;
      // window.scrollTo(0, (top - 30));
      // Or some other custom behaviour...
    }; 
  });
});

ハブラスが述べたように、<ui-view>これを適用したくない場合は、単にautoscroll="false"。私は実際のスクロールの実装をよく見ていないので、デコレータの方法(それはたくさんの楽しみです)を代替として言及するだろうと考えました。正確なスクロール動作を解決できると確信しています。

52
Kasper Lewau

パスが変更されるたびに、ルーターはイベントをブロードキャストします:$ stateChangeSuccessつまりURLが変更されたので、それを聞いてjqueryを使用してページの上部までスクロールします

$rootScope.$on('$stateChangeSuccess',function(){
    $("html, body").animate({ scrollTop: 0 }, 200);
})

上記のコードを内部に配置します

yourAppName.run(function(){

    //the above code here
 })
41
Rishul Matta

だから私はこれと同じ問題を抱えていた。固定トップのナビゲーションバーがあります。 ui-viewにautoscroll = "true"を設定すると、スクロールバーの高さの高さを引いた上にスクロールします。

だから私は一番上のナビゲーションバーのボディにパディングを追加したスタイルを取り除きました

// fixed navigation at top
//body { padding-top: 100px; }

そして、それをUIビューに適用しました

[ui-view=main] {
    padding-top: 100px;
}

Autoscroll = "true"が期待どおりに機能するようになりました。

12
Martin

1)autoscroll="false" ui-viewで、$viewContentLoadedイベント。

2)これは、アンカーに対するブラウザのデフォルトの動作です

7
VladN

$stateChangeSuccessは現在のAngularJS(1.2.xとして)ではもう利用できないようです。RishulMattasの例を次のように変更しました。

app.run(function ($rootScope) {
  $rootScope.$on('$viewContentLoaded',function(){
    jQuery('html, body').animate({ scrollTop: 0 }, 200);
  });
});
5
hoeni

上に置く

<div id="top">.....

スクロールするコード:

$rootScope.$on('$stateChangeStart', function() {
    $anchorScroll('top');
});
2
user3706408

ナビゲーション状態が子状態の場合、上にスクロールする必要はないと思うので、これを書きました。

$rootScope.$on('$stateChangeSuccess',function(_, _, _, os){
    if(!$state.includes(os) || $state.is(os))
        $("html, body").animate({ scrollTop: 0 }, 200);
});
1
karaxuna

Angular + Material Designを組み合わせた場合、上にスクロールするにはこれも必要です。

app.run(function ($rootScope) {
    $rootScope.$on('$viewContentLoaded', function () {
        $("md-content").animate({ scrollTop: 0 }, "fast"); /* <------- Notice this line */
        jQuery('html, body').animate({ scrollTop: 0 }, 200);
    });
});
1
Eli Livshitz

ほとんどの場合、ページの一番上までスクロールするだけでは十分ではありません。アンカーリンクを尊重し、場所のハッシュで指定されたロード済みコンテンツの特定の場所にスクロールすることは常に良い考えです。

この戦略を実装するために使用するコードは次のとおりです。

module.run(function (
  $rootScope,
  $timeout,
  $location,
  $uiViewScroll
) {

  // Scrolling when screen changed.
  $rootScope.$on('$viewContentLoaded', function () {
    $timeout(performAutoScroll, 0);
  });


  function performAutoScroll () {
    var hash = $location.hash();
    var element =
         findDomElement('#' + hash)
      || findDomElement('a[name="' + hash + '"]')
      || angular.element(window.document.body)
    ;
    $uiViewScroll(element);
  }
});

$viewContentLoadedは、コンテンツがui-view要素内にロードされたときにAngularによって生成されるイベントです。実際には、コードを移動するには、コードの実行を延期する必要がありますこの方法では、ビュー要素のコンテンツが実際にDOMツリーに配置されるため、クエリを実行できます$timeout遅延ゼロのトリックがこの目的に使用されます。

I Routerによって提供される$uiViewScrollサービスは、実際にスクロールを行うために使用されます。それにjQuery/jqLit​​e要素を渡すことができ、それは上境界までスクロールします。

$locationサービスから正しいハッシュを取得し、それを使用してDOMツリー内の適切な要素を見つけています。 id属性を持つ要素、またはname属性を持つリンクのいずれかです。スクロールする要素が見つからない場合は、body要素にフォールバックします(つまり、ページの上部にスクロールします)。

そして、findDomElementは単なる構文上の砂糖です。次のように定義されました:

/**
 * @param {string} selector
 * @returns {jQuery|null}
 */
function findDomElement (selector) {
  var result = $(selector);
  return (result.length > 0 ? result : null);
}

このアプローチが理にかなっており、外部の誰かに役立つことを願っています。乾杯!

0
Slava Fomin II

条件付きでビューでこれを行いたい場合は、次のようにコントローラービューに配置できます。

.state('exampleState', {
    url: '/exampleURL',
    controller: 'ExampleCtrl as examplectrl',
    onEnter: function($rootScope) {
            $rootScope.$on('$viewContentLoaded',function(){
            jQuery('html, body').animate({ scrollTop: 0 }, 200);
        });
    }
}).

または、必要に応じて、state.jsファイルをよりきれいに保ち、上記のビューのコントローラーに上記を配置します。

function ExampleCtrl ($scope, $rootScope) {

    $rootScope.$on('$viewContentLoaded',function(){
            jQuery('html, body').animate({ scrollTop: 0 }, 200);
        });
}

これが誰かを助けることを願って、私が何かを逃しているならば、私に知らせてください。私は後者を使用し、私にとっては素晴らしい作品です。

0
alphapilgrim