2013-07-15 1 views
9

gemacht, um Daten von meinem Server und dann legen Sie die Daten in eine Tabelle Raster wie diese habe ich:Wie Zeilen in einem Raster speichern, die ich eine Veränderung ng-Ressource

<div ng-form name="grid"> 
     <button type="submit" data-ng-disabled="grid.$pristine">Save</button> 
     <div class="no-margin"> 
      <table width="100%" cellspacing="0" class="form table"> 
       <thead class="table-header"> 
        <tr> 
         <th>ID</th> 
         <th>Title</th> 
        </tr> 
       </thead> 
       <tbody class="grid"> 
        <tr data-ng-repeat="row in grid.data"> 
         <td>{{ row.contentId }}</td> 
         <td><input type="text" ng-model="row.title" /></td> 
        </tr> 
       </tbody> 
      </table> 
     </div> 
</div> 

Gibt es eine Möglichkeit dass ich es so machen kann, dass das Klicken auf die Submit-Schaltfläche das Raster nach den geänderten Zeilen durchsucht und dann eine putEntity(row)-Funktion mit der Zeile als Argument aufruft?

+2

können Sie so etwas tun: http://jsfiddle.net/MGnAN/ – Atrix1987

Antwort

11

Sie könnten dies auf verschiedene Arten tun und sich daran erinnern, dass jeder NgModelController ein $ dirty Flag hat, mit dem Sie überprüfen können, ob sich die Eingabe geändert hat. Aber ich würde sagen, der einfachste Weg ist, einfach, dies zu tun:

bearbeiten zu HTML:

<input type="text" ng-model="row.title" ng-change="row.changed=true" /> 
<button ng-click="save()">Save</button> 

In JS:

$scope.save = function() { 
    // iterate through the collection and call putEntity for changed rows 
    var data = $scope.grid.data; 
    for (var i = 0, len = data.length; i < len; i++) { 
     if (data[i].changed) { 
      putEntity(data[i]); 
     } 
    } 
} 
+0

Danke. Ich werde das untersuchen und überprüfen. – Melina

+0

Ich mag die Einfachheit dieses Ansatzes.Erinnern Sie sich jedoch daran, dass Sie ein Änderungsereignis für alle bearbeitbaren Eigenschaften Ihres Objekts benötigen würden, da dies nur Änderungen berücksichtigt, die an 'row.title' vorgenommen wurden. – AndersDaniel

+0

Wenn t Hat ein Problem, können Sie das Änderungsereignis immer auf einem übergeordneten Element abfangen. jquery's Event-Blasen ändern, so dass Sie einfach eine Direktive erstellen und sie an das Eltern-Div anhängen können, das folgendes tut: element.on ('change input', function (evt) {/ * ... * /}); – brentmckendrick

4

Here's something that could work. Es wird mit dem JSFiddle aus dem ersten Kommentar als Grundlage erstellt.

Zuerst habe ich das data-ng-disabled Attribut zu changes.length <= 0 geändert und $scope.changes = [] zum Controller hinzugefügt.

$scope.changes = []; 

Dann habe ich eine Uhr auf $scope.data

$scope.$watch('data', function(newVal, oldVal){ 
    for(var i = 0; i < oldVal.length; i++){ 
     if(!angular.equals(oldVal[i], newVal[i])){ 
      console.log('changed: ' + oldVal[i].name + ' to ' + newVal[i].name); 

      var indexOfOld = $scope.indexOfExisting($scope.changes, 'contentId', newVal[i].contentId); 

      if(indexOfOld >= 0){ 
       $scope.changes.splice(indexOfOld, 1); 
      } 

      $scope.changes.push(newVal[i]); 
     } 
    } 
}, true); // true makes sure it's a deep watch on $scope.data 

Im Grunde ist dies das Array und prüft durchläuft, wenn etwas mit angular.equals verändert hat. Wenn ein Objekt geändert wurde, wird es überprüft, ob es bereits in $scope.changes existiert. Wenn dies der Fall ist, wird es entfernt. Danach newVal[i]-$scope.changes

gedrückt wird Die $scope.indexOfExisting von this SO question

$scope.indexOfExisting = function (array, attr, value) { 
    for(var i = 0; i < array.length; i += 1) { 
     if(array[i][attr] === value) { 
      return i; 
     } 
    } 
}; 

genommen Schließlich habe ich den $scope.checkChange() aussehen wie so

$scope.checkChange = function(){ 
    for(var i = 0; i < $scope.changes.length; i++){ 
     console.log($scope.changes[i].name); 
     //putEntity($scope.changes[i]) 
    } 
    $scope.changes = []; 
}; 

Dies gibt Ihnen dann die Möglichkeit, nur die einreichen Zeilen wurden geändert.

+0

Vielen Dank Anders. Ich werde das überprüfen und auch nur kurz warten, bis jemand anderes eine andere Lösung hat, bevor er akzeptiert wird. – Melina

+0

Warum nicht die schmutzige Prüfung nur, wenn der Benutzer auf Senden klickt? Durch die Registrierung von $ scope. $ Watch und die Verwendung der Gleichheitsüberprüfung können Sie je nach der Länge Ihres $ scope.data-Objekts und der Komplexität der Objekte möglicherweise enorme Performance-Kosten verursachen. – hgcrpd

+0

hgcrpd - Ich denke du bist hier richtig. Ich habe viele Datenzeilen und jede Zeile hat ziemlich viele Informationen. Scope.data zu beobachten scheint keine gute Lösung zu sein, denn es gibt viel zu sehen. Wie es aussieht, kann ich diese Lösung nicht wirklich akzeptieren :-( – Melina

2

entschied ich mich, dies zu tun, wie folgt:

Hier bekomme ich die Daten und mache dann eine Kopie davon:

getContents: function ($scope, entityType, action, subjectId, contentTypeId, contentStatusId) { 
    entityService.getContents(entityType, action, subjectId, contentTypeId, contentStatusId) 
    .then(function (result) { 
     $scope.grid.data = result; 
     $scope.grid.backup = angular.copy(result); 
     $scope.grid.newButtonEnabled = true; 
    }, function (result) { 
     alert("Error: No data returned"); 
     $scope.grid.newButtonEnabled = false; 
    }); 
}, 

Dann später, wenn es um das Sparen geht, benutze ich eckig.gleich mit einem Backup zu vergleichen:

$scope.saveData = function() { 
    var data = $scope.grid.data; 
      for (var i = 0, len = $scope.grid.data.length; i < len; i++) { 
       if (!angular.equals($scope.grid.data[i], $scope.grid.backup[i])) { 
        var rowData = $scope.grid.data[i] 
        var idColumn = $scope.entityType.toLowerCase() + 'Id'; 
        var entityId = rowData[idColumn]; 
        entityService.putEntity($scope.entityType, entityId, $scope.grid.data[i]) 
         .then(function (result) { 
          angular.copy(result, $scope.grid.data[i]); 
          angular.copy(result, $scope.grid.backup[i]); 
         }, function (result) { 
          alert("Error: " + result); 
         }) 
       } 
      } 
      $scope.grid.newButtonEnabled = true; 
      $scope.grid.saveButtonEnabled = false; 
      $scope.$broadcast('tableDataSetPristine'); 
    } 
+0

hmm. warum würdest du es so machen und nicht den ng-change Weg, der viel effizienter ist und weniger Code benötigt? – brentmckendrick

+0

@brentmckendrick - Ich stimme zu, Ihr Weg ist effizienter und ich änderte Ihre Antwort zu akzeptieren. Danke für Ihre Hilfe :-) – Melina

3

Ich habe etwas ganz ähnlich für mich, und ich verwendet, um eine andere Art und Weise, habe ich beschlossen, alle ng-Modelle binden an die Daten direkt an, die mich mit den Indizes arbeiten lassen wenn ich jede Zeile überprüfen muss, aber ich könnte auch entscheiden, die gesamten Daten an den Server zu senden

Dann muss ich nur alle Änderungen an jedem Index (auch mit großen Daten, ich muss nur hinzufügen/lösche eine Ganzzahl) und speichere sie in einem Array

Sobald ich fertig bin, kann ich auf den Submit-Button klicken, der auf jedem Index, den ich berührt habe, eine Schleife macht, um zu prüfen, ob Inhalt ist wirklich anders als der ursprüngliche, und dann kann ich tun, was ich will damit (wie eine putEntity-Funktion aufrufen, wenn ich eine hatte)

Ich machte eine Geige basierend auf Ihrem HTML-Code, wird es einfacher zu spielen sie mit ihm als mit einer kopieren/Einfügen des Codes hier: http://jsfiddle.net/DotDotDot/nNwqr/1/

die wichtigste Änderung im HTML dieser Teil ist, das Binden des Modells an die Daten und das Hinzufügen einer Änderungsempfänger

<td><input type="text" ng-model="data[$index].title" ng-change="notifyChange($index)"/></td> 

ich denke, das JavaScript-Teil ist durchaus verständlich, ich protokolliere Indizes, während die Daten geändert werden, und später, wenn ich auf die Schaltfläche zum Senden klicken, kann es Rufen Sie die richtige Funktion nur für die geänderten Zeilen auf, basierend auf den geloggten Indizes

Verwandte Themen