2016-10-31 1 views
0

Ich arbeite an einer angularJS-Anwendung mit einer Seite, auf der ich ungefähr 30 Elemente mit ng-repeat anzeigen kann. Vor jedem Objekt befindet sich eine Umschalttaste (aktiviert/deaktiviert). Mit dem aktuellen Code, den ich habe, kann ich diese Elemente umschalten. Aber das Problem ist, wenn ich scrolle nach unten und umschalten lässt sagen Artikel 25, dann scrollt es automatisch zum oberen Rand der Seite. Wenn ich jetzt nach unten scrolle, kann ich sehen, dass der Wechsel tatsächlich stattgefunden hat.
Jetzt müssen Sie sicherstellen, dass die Bildlaufposition beibehalten wird, nachdem auf die Schaltfläche geklickt wurde.Scroll-Position beibehalten, wenn eine Schaltfläche umgeschaltet wird

Bitte siehe unten den Code, den ich habe.

HTML

<div id="eventTypes" class="panel-body"> 
    <div ng-if="!spinner" ng-repeat="item in items" class="panel-body"> 
     <div class="row"> 
      <div class="col-md-9">{{item.itemName)}}</div> 
      <div class="col-md-3"> 
       <input id="toggleEnabled" 
         type="button" 
         ng-class="{'btn-primary': item.enabled}" 
         value="{{item.enabled ? 'enabled' : 'disabled'}}" 
         ng-click="toggleEnabled(item)"> 
      </div> 
     </div> 
    </div> 
    <div ng-if="spinner" class="spinner"> 
     <div class="spinner-container container1"> 
      <div class="circle1"></div> 
      <div class="circle2"></div> 
      <div class="circle3"></div> 
      <div class="circle4"></div> 
      </div> 
     <div class="spinner-container container2"> 
      <div class="circle1"></div> 
      <div class="circle2"></div> 
      <div class="circle3"></div> 
      <div class="circle4"></div> 
     </div> 
     <div class="spinner-container container3"> 
      <div class="circle1"></div> 
      <div class="circle2"></div> 
      <div class="circle3"></div> 
      <div class="circle4"></div> 
     </div> 
    </div> 
</div> 

JS

(function() { 
    'use strict'; 
    angular.module('myApp').controller('itemsController', function ($scope, itemsService) { 
     var serviceError = function (errorMsg) { 
      console.log(errorMsg); 
      $scope.turnOffSpinner(); 
     }; 

     $scope.items = []; 
     $scope.item = {}; 
     $scope.spinner = true; 

     $scope.toggleEnabled = function (item) { 
      $scope.turnOnSpinner(); 
      itemsService.toggleEnabled(item) 
       .then(function() { 
        $scope.loaditems(); 
       }); 
     }; 

     $scope.loaditems = function() { 
      itemsService.getitems().then(function (response) { 
       $scope.items = response.data; 
      }, serviceError); 
      $scope.turnOffSpinner(); 
     }; 

     $scope.turnOnSpinner = function() { 
      $scope.spinner = true; 
     }; 

     $scope.turnOffSpinner = function() { 
      $scope.spinner = false; 
     }; 

     $scope.loaditems(); 
    }); 
}()); 

Wie das jetzt funktioniert, sobald ich auf den Schalter klicken, wird ein Spinner aktiviert. In der Zwischenzeit wird der Controller die itemService.toggleEnabled() Methode aufrufen, die einen Ajax-Aufruf an den Server ausführt, um einfach den Status des Elements (aktiviert zu deaktiviert oder umgekehrt) im Backend zu ändern. Bei erfolgreicher Statusänderung und wenn der Ajax-Aufruf zurückkommt, wird im Controller die Methode $scope.loadItems() aufgerufen. Diese Methode führt dann einen weiteren Ajax-Aufruf aus, um die Elemente abzurufen (jetzt mit dem aktualisierten Status des Elements, das umgeschaltet wurde). Der Spinner ist deaktiviert und die Daten werden dann auf der Benutzeroberfläche angezeigt. Wenn das alles erledigt ist, wird die Seite nach oben gescrollt. Dies ist ärgerlich, wenn ich ein Objekt in der Liste umschalten möchte. Ich möchte, dass die Seite an der gleichen Position angezeigt wird, wenn ich auf die Umschaltfläche des entsprechenden Elements klickte und nicht nach oben scrollte.

Ich bin neu in AngularJS und jede Hilfe in dieser Hinsicht wäre wirklich hilfreich.

+1

ich frage mich, ob, wenn Sie die Liste erneut abrufen, ruft es $ scope.loadItems (..), wenn er die Liste löscht die Seite zu kürzen, damit sie nach oben scrollt, wenn die Seite kürzer ist? –

+0

Ich glaube nicht, dass es so passiert. Auch wenn es so ist, wie könnte ich verhindern, dass es nach oben scrollt? –

Antwort

2

Es sieht aus wie Ihr Spinner Schema ist, was Sie Probleme verursacht:

... 
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body"> 
... 
<div ng-if="spinner" class="spinner"> 
... 

Jedes Mal, wenn Sie Ihre Schaltfläche klicken, die Sie in Ihrem ng-repeat jedes einzelne Element zu entfernen aus dem DOM, wenn Sie $scope.turnOnSpinner(). Deshalb scheint es, an die Spitze zu springen. Es springt nicht wirklich, es gibt einfach nicht genug DOM-Elemente, um die Seite zu füllen, wodurch die Seite so kurz wird, dass die Bildlaufleiste verschwindet (selbst wenn es nur für eine Sekunde ist). Wenn der Spinner dann fertig ist, füllt Ihre ng-repeat die Seite erneut mit DOM-Elementen, was dazu führt, dass Ihre Bildlaufposition verloren geht.

Also im Grunde, was Sie versuchen zu beheben ist ein Symptom für eine weniger als ideale Lade Spinner Implementierung.

ng-if ist eine "brutale" Art, Dinge in Angular zu verstecken. Es ist hauptsächlich dazu gedacht, die Dinge für einen längeren Zeitraum zu verbergen als "weichere" Anweisungen wie ng-show/ng-hide.Eine Lösung für Ihr Problem ist ng-disabled zu verwenden, auf jeder der Tasten der Benutzer die Interaktion mit ihm zu verhindern, während der Spinner aktiv ist, anstatt eine harte Entfernung jedes Elements tun:

Vorher:

<div ng-if="!spinner" ng-repeat="item in items" class="panel-body"> 
    <div class="row"> 
     <div class="col-md-9">{{item.itemName)}}</div> 
     <div class="col-md-3"> 
      <input id="toggleEnabled" 
        type="button" 
        ng-class="{'btn-primary': item.enabled}" 
        value="{{item.enabled ? 'enabled' : 'disabled'}}" 
        ng-click="toggleEnabled(item)"> 
     </div> 
    </div> 
</div> 

Nach:

<div ng-repeat="item in items" class="panel-body"> 
    <div class="row"> 
     <div class="col-md-9">{{item.itemName)}}</div> 
     <div class="col-md-3"> 
      <input id="toggleEnabled" 
        ng-disabled="spinner" 
        type="button" 
        ng-class="{'btn-primary': item.enabled}" 
        value="{{item.enabled ? 'enabled' : 'disabled'}}" 
        ng-click="toggleEnabled(item)"> 
     </div> 
    </div> 
</div> 

Eine andere Lösung, die ich mich wirklich mögen und verwenden diese Winkelmodul: https://github.com/darthwade/angular-loading

Sie können es an jedes Element auf der Seite anhängen und es wird ein Lade-Spinner darüber platziert und verhindert, dass Sie mit ihm interagieren, bis Ihr Ajax oder was auch immer getan wird.

Wenn Sie nicht über eine dieser beiden mögen, versuchen Sie Ihr ng-repeat in einen Behälter setzen, die Sie verwenden können Interaktion mit Ihren Elementen zu verhindern, wenn der Spinner ist oben:

<div class="container" ng-class="{'you-cant-touch-this': spinner}"> 
    <div ng-repeat="item in items" class="panel-body"> 
    <div class="row"> 
     <div class="col-md-9">{{item.itemName)}}</div> 
     <div class="col-md-3"> 
      <input id="toggleEnabled" 
        type="button" 
        ng-class="{'btn-primary': item.enabled}" 
        value="{{item.enabled ? 'enabled' : 'disabled'}}" 
        ng-click="toggleEnabled(item)"> 
     </div> 
    </div> 
    </div> 
</div> 

Jetzt können Sie es Stil in einige Wege-Interaktion zu verhindern, ohne alle diese Elemente aus dem DOM zu entfernen:

.you-cant-touch-this { 
    pointer-events: none; 
} 
+0

Ich habe versucht, den ersten Ansatz zu verwenden, aber wenn ich auf den Knopf klicke, passiert nichts. Die Schaltfläche scheint nicht mehr klickbar zu sein. –

+0

Entfernen Sie das '!' Aus dem 'Spinner'-Teil von' ng-disabled = "! Spinner" 'so, dass es so aussieht:' ng-disabled = "spinner" '. Ich habe meine Antwort aktualisiert. –

+0

Das hat es gelöst. Vielen Dank. Ich habe mich gefragt, ob Sie mir eine detailliertere Erklärung geben können, was bei meiner bisherigen Vorgehensweise schief gelaufen ist. –

Verwandte Themen