2016-08-03 5 views
0

Ich schrieb eine angularjs Direktive, um Ajax Spinner zu zeigen und zu verstecken. Die Sichtbarkeit des Spinner wird durch Schaltflächen zum Ein- und Ausblenden umgeschaltet, deren Funktionalität in den MainController geschrieben wird. Es gibt eine Variable innerhalb des Controllers, die basierend auf dem Knopfklick auf Wahr und Falsch gesetzt wird. Diese Variable wird mithilfe von isolate scope an die Direktive übergeben. Wenn ich versuche, einen Spinner umzuschalten, sind auch alle anderen Spinner sichtbar. Wie kann ich meinen Code ändern, um nur den bestimmten Spinner umzuschalten?toggling eine Direktive Effekte andere dircetive in ngrepeat

https://plnkr.co/edit/AFmBVbHaBPk66T7UjPC5?p=preview

// Code goes here 
 
angular.module('app',[]) 
 
    .controller('MainController',[MainController]) 
 
    .directive('loadingDirective',[loadingDirective]); 
 
    function MainController(){ 
 
    var mc = this; 
 
    mc.showMe = showMe; 
 
    mc.hideMe = hideMe; 
 
    mc.loading = false; 
 
    function showMe(){ 
 
     mc.loading = true; 
 
    } 
 
    function hideMe(){ 
 
     mc.loading = false; 
 
    } 
 
    } 
 
    function loadingDirective() { 
 
     return { 
 
     restrict: 'E', 
 
     replace:true, 
 
     scope:{ 
 
      loading:"=loading" 
 
     }, 
 
     template: '<span class="spinner">Loading…</span>', 
 
     link: function (scope, element, attr) { 
 
       scope.$watch('loading', function (val) { 
 
       
 
        if (val) 
 
         $(element).show(); 
 
        else 
 
         $(element).hide(); 
 
       }); 
 
     } 
 
     }; 
 
    }
/* Styles go here */ 
 

 
.spinner { 
 
    position: relative; 
 
    /* [1] */ 
 
    display: inline-block; 
 
    width: 1em; 
 
    /* [2] */ 
 
    height: 1em; 
 
    /* [2] */ 
 
    font-size: 32px; 
 
    /* [3] */ 
 
    border-bottom: 1px solid; 
 
    /* [4] */ 
 
    vertical-align: middle; 
 
    overflow: hidden; 
 
    /* [5] */ 
 
    text-indent: 100%; 
 
    /* [5] */ 
 
    -webkit-animation: 0.5s spinner linear infinite; 
 
    animation: 0.5s spinner linear infinite; 
 
    /** 
 
    * 1. Make the spinner a circle. 
 
    */ 
 
    /** 
 
    * The (optically) non-spinning part of the spinner. 
 
    * 
 
    * 1. Border around entire element fills in the rest of the ring. 
 
    * 2. Paler than the part that appears to spin. 
 
    */ 
 
} 
 
.spinner, .spinner:after { 
 
    border-radius: 100%; 
 
    /* [1] */ 
 
} 
 
.spinner:after { 
 
    content: ""; 
 
    position: absolute; 
 
    top: 0; 
 
    right: 0; 
 
    bottom: 0; 
 
    left: 0; 
 
    border: 1px solid; 
 
    /* [1] */ 
 
    opacity: 0.5; 
 
    /* [2] */ 
 
} 
 

 
/** 
 
* Size variants (built by adjusting `font-size`). 
 
*/ 
 
.spinner--small { 
 
    font-size: 16px; 
 
} 
 

 
.spinner--large { 
 
    font-size: 64px; 
 
} 
 

 
/** 
 
* Color overrides. 
 
*/ 
 
.spinner--light { 
 
    color: #fff; 
 
} 
 

 
.spinner--dark { 
 
    color: #333; 
 
} 
 

 
@-webkit-keyframes spinner { 
 
    to { 
 
    -webkit-transform: rotate(360deg); 
 
    } 
 
} 
 
@keyframes spinner { 
 
    to { 
 
    -webkit-transform: rotate(360deg); 
 
      transform: rotate(360deg); 
 
    } 
 
}
<!DOCTYPE html> 
 
<html ng-app="app"> 
 

 
    <head> 
 
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 
    </head> 
 

 
    <body> 
 
    <h1>Hello Plunker!</h1> 
 
    <div ng-controller="MainController as mc"> 
 
     <div ng-repeat="i in [1,2,3,4,5]"> 
 
     <loading-directive loading="mc.loading"></loading-directive> 
 
     <button ng-click="mc.showMe()">show</button> 
 
     <button ng-click="mc.hideMe()">hide</button> 
 
     </div> 
 
    </div> 
 
    </body> 
 

 
</html>

+0

[Icycool] (http://stackoverflow.com/users/5039495/icycool) Antwort ist besser geeignet für mein Problem da ich das Umschalten des Spinners vor und nach einem Ajax-Aufruf steuern muss, um das Laden zu signalisieren. Die von [Nivedit] (http://stackoverflow.com/users/5002305/nivedit) zur Verfügung gestellte Lösung ist jedoch sehr allgemein und kann in vielen Situationen verwendet werden. Vielen Dank für die Hilfe Jungs. –

Antwort

2

Wenn Sie die Spinner wollen ihre eigenen Staaten haben, dann sollten sie durch verschiedene Variablen gesteuert werden.

In Ihrem Beispiel ist es erreichbar durch eine Anordnung mit den Variablen

<div ng-repeat="i in [1,2,3,4,5]"> 
    <loading-directive loading="mc.loading[i]"></loading-directive> 
    <button ng-click="mc.show(i)">show</button> 
    <button ng-click="mc.hide(i)">hide</button> 
</div> 

mc.loading = {}; 
function show(i){ 
    mc.loading[i] = true; 
} 
function hide(i){ 
    mc.loading[i] = false; 
} 

In einer realen Fallbeispiel zu halten, wo Sie einige Daten haben, und Sie verwenden ng-repeat über sie, sollten Sie die Ladezustände innerhalb zuweisen die Elemente selbst.

Dies ist eine übliche Technik Zustand zu jedem Artikel in ng-repeat

mc.fruits = [ 
    {name:"apple"}, 
    {name:"orange"}, 
    {name:"starfruit"} 
] 

function load(fruit) { fruit.loading = true; } 
function noLoad(fruit) { fruit.loading = false; } 

<div ng-repeat="fruit in mc.fruits"> 
    <loading-directive loading="fruit.loading"></loading-directive> 
    {{fruit.name}} 
    <button ng-click="mc.load(fruit)">show</button> 
    <button ng-click="mc.noLoad(fruit)">hide</button> 
</div> 
1

Die loading Variable beobachtete gemeinsam ist für alle Richtlinien an, damit, wenn das Modell die Uhr Zustand 5 mal in Ihrem Fall läuft geändert wird, werden alle Spinnern zu entfernen .

Ich benutzte die index zu sehen, was verborgen oder gezeigt wird,

Aktualisiert Geige: https://plnkr.co/edit/Jjfk6v7TJZHlQicM45ln?p=preview

HTML

<div ng-repeat="i in [1,2,3,4,5]"> 
    <loading-directive data-index="{{$index}}" loading="mc.loading" offset="mc.offset"></loading-directive> 
    <button ng-click="mc.showMe($index)">show</button> 
    <button ng-click="mc.hideMe($index)">hide</button> 
    </div> 

Angular

angular.module('app',[]) 
.controller('MainController',[MainController]) 
.directive('loadingDirective',[loadingDirective]); 
function MainController(){ 
var mc = this; 
mc.showMe = showMe; 
mc.hideMe = hideMe; 
mc.loading = false; 
mc.offset =-1; 
function showMe(offset){ 
    mc.loading = true; 
    mc.offset = offset; 
} 
function hideMe(offset){ 
    mc.loading = false; 
    mc.offset = offset; 
    console.log(offset); 
} 
} 
function loadingDirective() { 
    return { 
    restrict: 'E', 
    replace:true, 
    scope:{ 
     loading:"=loading", 
     offset:"=offset" 
    }, 
    template: '<span class="spinner">Loading…</span>', 
    link: function (scope, element, attr) { 


      scope.$watch('[loading, offset]' , function (val) { 

      if(attr.index == scope.offset || scope.offset == -1){ 
       if (val[0]) 
        element.show(); 
       else 
        element.hide(); 
      } 
      }); 
    } 
    }; 
} 
1
SCRIPT: 

    function showMe(i){ 
    mc.loading = true; 
    i=true; 
    } 

IN HTML hinzufügen, um dieses

<div ng-repeat="i in [1,2,3,4,5]"> 
<span><loading-directive loading="mc.loading" ng-show="i==true"></loading-directive> 
    <button ng-click="mc.showMe(i)">show</button></span> 
    <button ng-click="mc.hideMe()">hide</button> 
    </div> 
1

Arbeits Plunkr zuweisen:https://plnkr.co/edit/peGDxYJzKJgiHuPp4zmQ

Sie benötigten, um den isolierten Umfang in der Richtlinie korrekt zu definieren. Im Wesentlichen war Ihre Anweisung immer noch vom Controller abhängig, da Sie dieselbe Variable mc.loading verwendeten, um den Status aller Direktiveninstanzen zu ermitteln.

Durch Verschieben der deterministischen Variablen $scope.loading sowie der Schaltflächen innerhalb der Direktive isolieren wir jede Direktiveninstanz vollständig und machen sie zu vollständig unabhängigen Einheiten.

HTML:

<div ng-controller="MainController as mc"> 
    <div ng-repeat="i in [1,2,3,4,5]"> 
    <loading-directive></loading-directive> 
    </div> 
</div> 

JS:

angular.module('app',[]) 
    .controller('MainController',[MainController]) 
    .directive('loadingDirective',[loadingDirective]); 
    function MainController(){ 
    } 
    function loadingDirective() { 
     return { 
     restrict: 'E', 
     replace:true, 
     scope:{}, 
     template: '<div><span ng-if="loading" class="spinner">Loading…</span>' 
     + '<button ng-click="showMe()">show</button>' 
     + '<button ng-click="hideMe()">hide</button></div>', 
     controller: function($scope) { 
       $scope.showMe = showMe; 
       $scope.hideMe = hideMe; 
       function showMe(){ 
       $scope.loading = true; 
       } 
       function hideMe(){ 
       $scope.loading = false; 
       } 
     } 
     }; 
    }