2016-07-06 3 views
1

Ich habe eine Komponente erstellt, die verwendet wird, um HTML-Tabellen die Funktion "Datenraster" hinzuzufügen. Die Header sind anklickbar, um das Sortieren der Daten (aufsteigend/absteigend) für diese Spalte zu ermöglichen. Bis jetzt funktioniert es großartig, es sei denn, ich habe zwei Instanzen der Komponente auf der gleichen Seite. Wenn ich auf eine Kopfzeile in einer Tabelle klicke, wirkt sich dies auf beide Tabellen aus.Isolieren von Ereignissen in Angular 1.5-Komponenteninstanzen

Gibt es eine Möglichkeit, die ich vermisse, um die Ereignisse der Komponente zu isolieren, um nur diese Instanz zu beeinflussen?

Komponente:

angular.module('app') 
     .component('datagrid', { 
      templateUrl:'components/datagrids/datagrids.component.html', 
      controller:DatagridController, 
     }) 

Controller (Work in progress, ich weiß, es ist ein bisschen ein Durcheinander im Moment!):

function DatagridController($filter, datagridService){ 
    var ctrl = this; 
    ctrl.today = new Date(); 
    ctrl.sortBy = null; 
    ctrl.fields = []; 
    ctrl.data = []; 
    ctrl.update = function(){ 
     var service = datagridService; 
     console.log(datagridService); 
     var updatedFields = []; 
     console.log(datagridService.fields); 
     for(var i = 0; i < datagridService.fields.length; i++){ 
      var fieldName = datagridService.fields[i]; 
      var fieldDirection = (ctrl.fields.length === 0) ? 'ascending' : ctrl.fields[i].direction; 
      updatedFields.push({name:fieldName, direction:fieldDirection}); 
     } 
     ctrl.fields = updatedFields; 
     console.log(ctrl.fields) 
     if (ctrl.sortBy == null){ ctrl.sortBy = $filter('toCamelCase')(ctrl.fields[0].name); } 
     ctrl.data = datagridService.data.sort(ctrl.sortData(ctrl.sortBy)); 
     ctrl.today = new Date(); 
    }; 
    ctrl.sortData = function(field, reverse, primer){ 
     console.log(field + ' | ' + reverse) 
     var key = primer ? 
      function(x) {return primer(x[field])} : 
      function(x) {return x[field]}; 
     reverse = !reverse ? 1 : -1; 
     ctrl.sortBy = field; 
     return function (a, b) { 
      return a = key(a), b = key(b), reverse * ((a > b) - (b > a)); 
     } 
    }; 
    ctrl.toggleSortDirection = function(index){ 
     console.log(index); 
     var field = ctrl.fields[index]; 
     console.log(field); 
     var fieldName = field.name; 
     console.log(fieldName); 
     var direction = ctrl.fields[index].direction; 
     console.log(direction); 
     var reverse = (direction == 'ascending') ? true : false; 
     console.log(reverse); 
     var direction = (direction === 'ascending') ? 'descending' : 'ascending'; 
     console.log(direction); 
     for(var i = 0; i < ctrl.fields.length; i++){ 
      ctrl.fields[i].direction = 'ascending'; 
     } 
     ctrl.fields[index].direction = direction; 
     ctrl.data.sort(ctrl.sortData($filter('toCamelCase')(fieldName), reverse)); 
    }; 
    ctrl.validDatetime = function(dt){ 
     //this should probably be a service 
     console.log(dt); 
     var rx = /([0-9]{4})\-([0-9]{2})\-([0-9]{2})/; 
     if(dt.match(rx)){ console.log(dt); } 
     return (dt.match(rx)) ? true : false; 
    }; 
    ctrl.$onInit = ctrl.update(); 
} 
DatagridController.$inject = ['$filter', 'datagridService']; 

Vorlage:

<table ng-if="$ctrl.data.length > 0" class="datagrid"> 
    <caption ng-if="$ctrl.caption">{{ $ctrl.caption }}</caption> 
    <colgroup ng-if="$ctrl.colgroup.length > 0"> 
     <col ng-repeat="col in $ctrl.colgroup"> 
    </colgroup> 
    <thead ng-if="$ctrl.hasHeader = true"> 
     <tr>  
      <th ng-repeat="field in $ctrl.fields" ng-click="$ctrl.toggleSortDirection($index)" data-sortable="true">{{ field.name }}<div ng-class="field.direction"></div></th> 
     </tr> 
    </thead> 
    <tbody> 
     <tr ng-repeat="record in $ctrl.data"> 
      <td ng-repeat="field in $ctrl.fields"> 
       <span ng-if="!$ctrl.validDatetime(record[(field.name|toCamelCase)])"><a>{{ record[(field.name|toCamelCase)] }}</a></span> 
       <span ng-if="$ctrl.validDatetime(record[(field.name|toCamelCase)])"><a>{{ record[(field.name|toCamelCase)] | date: 'dd-MMM-yyyy' }}</a></span> 
      </td> 
     </tr> 
    </tbody> 
    <tfoot ng-if="$ctrl.hasFooter = true"> 
     <td colspan="{{ $ctrl.fields.length }}">Last Updated: {{ $ctrl.today | date: 'dd-MMM-yyyy' }}</td> 
    </tfoot> 
</table> 

Component Tag:

<datagrid></datagrid> 
+0

Wie werden Sie Controller in Ihrer Vorlage zuweisen? Ich habe eine ähnliche App, wo mehrere und ähnliche DOM-Objekte den gleichen Controller zugewiesen haben. Standardmäßig haben alle ihre eigenen Instanzen dieses Controllers. – MadPhysicist

+0

Ich habe die Dokumentation, die ich über Angular Components gefunden habe, befolgt, und nach dem, was ich gelesen habe, ist der Controller der Komponente zugewiesen. Ich habe kein Beispiel für den Controller gesehen, der bei dieser Methode an die Vorlage angehängt wird. Die Komponente wird dann in die Seite über die Tag – Eric

Antwort

1

Komponenten sind standardmäßig isoliert, was bedeutet, dass es für jede Instanz eigene gibt.

Die Sache ist, dass Daten durch Service geteilt werden. Zum Beispiel machen Sie datagridService.data.sort in der ersten Instanz => es ändert Daten in Service => es wird in allen Instanzen Ihrer Komponente (es gibt ein data Objekt im Speicher, auf die Sie versuchen zuzugreifen).

Ein Fix könnte sein, Kopien von Daten für jede Komponenteninstanz zu erstellen.

ctrl.data = Object.assign([], datagridService.data); 

Dont direkt Manipulationen tun auf datagridService.data, sondern verwenden ctrl.data statt

+1

Dank ein Haufen, oKonyk. Ich war so in die Fälle verstrickt, dass ich nicht daran dachte, das zu sehen! – Eric

+0

Sicher! Freue mich zu helfen! – oKonyk