wake-up-neo.com

Angularer UI-Router nach oben scrollen, nicht zur UI-Ansicht

Ich habe gerade ein Upgrade von ui-router 0.2.8 auf 0.2.0 durchgeführt, und ich habe festgestellt, dass bei Änderungen des Status die Bildlaufposition an das obere Ende des untergeordneten Objekts ui-view springt, das sich im neuen Zustand befindet.

Das ist in Ordnung, aber ich habe zwei Probleme damit:

1) Ich habe eine 30px-Auffüllung zwischen dem oberen Rand der Seite und dem ui-view und ich möchte, dass der Bildlauf an den oberen Rand der Seite verschoben wird, sodass eine Lücke entsteht. Im Moment geht es genau an die Spitze des ui-view, was hässlich aussieht. Um dies zu erreichen, muss ich entweder wissen, wie ich dazu komme, zum oberen Teil des Divis zu scrollen, in dem sich die Ui-Ansicht befindet (nicht der Browser viewport), oder ich muss herausfinden, wie ich $uiViewScroll überschreiben kann, um zum zu scrollen ui-view minus 30px.

Ich habe $uiViewScrollProvider.useAnchorScroll(); ausprobiert, aber wenn ich das tue, scrollt es überhaupt nicht. Ich habe auch <ui-view autoscroll="false">; ausprobiert, wodurch auch das Scrollen vollständig gestoppt wird.

2) Im Moment blättert es nicht wirklich, sondern springt. Soll ein Scrollen erfolgen oder liegt es an dem Entwickler, dies mit CSS-Übergängen zu tun?

Jede Hilfe wäre wirklich dankbar :)

64
jonhobbs

Ein anderer Ansatz besteht darin, den Standard-$uiViewScroll-Dienst zu dekorieren und das Standardverhalten effektiv zu überschreiben. 

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

Und wie Hubrus erwähnt hat, fügen Sie für jeden <ui-view>, den Sie nicht beantragen möchten, einfach autoscroll="false" hinzu. Ich habe mir die eigentliche Scroll-Implementierung nicht genau angeschaut, ich dachte nur, ich würde den Dekorateur-Weg (es macht viel Spaß) als Alternative erwähnen. Ich bin mir sicher, dass Sie das genaue Scrollverhalten herausfinden können. 

52
Kasper Lewau

wenn sich der Pfad ändert, sendet der Router ein Ereignis: $ stateChangeSuccess, d. h. die URL wurde geändert. Hören Sie sich einfach das Ereignis an und blättern Sie mit jquery zum Anfang der Seite

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

gib den obigen Code ein

yourAppName.run(function(){

    //the above code here
 })
41
Rishul Matta

Also hatte ich das gleiche Problem. Ich habe eine feste Navigationsleiste. Wenn ich autoscroll = "true" in die ui-view stelle, würde ich nach oben scrollen, abzüglich der Höhe der Bildlaufleiste.

Also habe ich den Stil entfernt, der die Polsterung für die obere Navigationsleiste hinzugefügt hat

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

Und wendete es auf die UI-Ansicht an

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

Jetzt funktioniert autoscroll = "true" wie erwartet.

11
Martin

1) Ich denke, es ist am einfachsten, autoscroll="false" in die Ui-Ansicht zu setzen und das Scrollen im $viewContentLoaded-Ereignis zu ändern.

2) Dies ist das Standardverhalten des Browsers für Anker

7
VladN

Da $stateChangeSuccess in der aktuellen Version von AngularJS (als 1.2.x) nicht mehr verfügbar zu sein scheint, habe ich Rishul Mattas Beispiel folgendermaßen geändert, was für mich gut funktioniert:

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

Darauf legen

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

Code zum Blättern:

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

Ich denke, dass wir nicht nach oben scrollen müssen, wenn der Navigationsstatus untergeordnet ist, also schrieb ich Folgendes:

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

Wenn Sie Angular + Material Design kombinieren, müssen Sie auch nach oben scrollen:

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

Meist reicht es nicht aus, nur zum oberen Rand der Seite zu scrollen. Es ist immer eine gute Idee, Ankerlinks zu respektieren und zu dem bestimmten Ort im geladenen Inhalt zu scrollen, der durch den Hash des Orts angegeben ist.

Hier ist der Code, den ich zur Umsetzung dieser Strategie verwende:

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 ist ein Ereignis, das von Angular generiert wird, wenn Inhalt in das ui-view-Element geladen wird. Tatsächlich müssen wir die Ausführung unseres Codes verschieben, um ihn in einen nächsten Digest-Zyklus zu verschieben. Auf diese Weise wird der Inhalt des view-Elements tatsächlich in die DOM-Baumstruktur eingefügt, sodass wir ihn abfragen können. Für diesen Zweck wird $timeout ohne Verzögerungstrick verwendet.

Der $uiViewScroll-Dienst, bereitgestellt von UI Router , wird verwendet, um das Scrollen durchzuführen. Wir können ein jQuery/jqLite-Element an das Element übergeben und es wird zum oberen Rand blättern.

Wir erhalten den currect-Hash vom $location-Dienst und verwenden ihn, um das richtige Element im DOM-Baum zu finden. Dies kann entweder ein Element mit dem Attribut id oder ein Link mit dem Attribut name sein. Falls wir kein Element finden können, zu dem gescrollt werden kann, fallen wir auf ein body-Element zurück (d. H. Zum oberen Seitenrand blättern).

Und die findDomElement ist nur ein syntaktischer Zucker. Es definiert sich wie folgt:

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

Ich hoffe, dass dieser Ansatz sinnvoll ist und jemandem da draußen nützlich sein wird. Prost!

0
Slava Fomin II

Wenn Sie dies mit bedingten Ansichten tun möchten, können Sie dies wie folgt in der Controller-Ansicht platzieren:

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

oder optional, wodurch Ihre state.js-Datei sauberer bleibt. Platzieren Sie das Obige im Controller für die angegebene Ansicht: 

function ExampleCtrl ($scope, $rootScope) {

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

Hoffe das hilft jemandem, bitte lass es mich wissen, wenn mir etwas fehlt. Ich habe das letztere benutzt und funktioniert super für mich.

0
alphapilgrim