2015-04-24 4 views
30

Ich rendere daten durch einen ng-wiederholung zyklus. Und ich möchte es aktualisieren, während ich das Array aktualisiere. Von dem, was ich lese, sollte dies automatisch geschehen, aber das funktioniert nicht. Also, was mache ich falsch?ng-repeat nicht update auf update von array

html:

<tr ng-repeat="data in dataDifferenceArray"> 
    <td> 
     {{data.name}} 
    </td> 
    <td> 
     {{data.startData}} 
    </td> 
    <td> 
     {{data.endData}} 
    </td> 
    <td> 
     {{data.differenceData}} 
    </td> 
</tr> 

Controller (diese Funktion auf eine Schaltfläche mit ng-Klick ausgelöst wird):

$scope.getDifferences = function() { 
    $scope.dataDifferenceArray = []; 
    var i; 
    for (i = 0; i < 20 ;i++) { 
    $scope.dataDifferenceArray.push({ 
     name : 30, 
     startData : 20, 
     endData : 2, 
     differenceData : 30 
    }) 
    } 
} 

console.log zeigt, dass das Array korrekt aktualisiert wird, aber die Tabelle in Meine Sicht ändert sich nicht. Ich weiß nicht, was ich falsch mache.

+2

Alle Fehler in der Konsole? Können Sie in einem Plunkr replizieren? – tymeJV

+1

Ist Ihr HTML korrekt an den Controller gebunden? – illiptic

Antwort

46

Das liegt daran, dass Sie die Array-Referenz in Ihrer Methode getDifferences ändern.

Um das zu vermeiden, uns Punkt, zum Beispiel mit "Controller als" Syntax: Ein weiterer https://github.com/angular/angular.js/wiki/Understanding-Scopes#ngRepeat

:

<div ng-controller="myController as c"> 
    [...] 

    <tr ng-repeat="data in c.dataDifferenceArray"> 
     <td> 
      {{data.name}} 
     </td> 
     <td> 
      {{data.startData}} 
     </td> 
     <td> 
      {{data.endData}} 
     </td> 
     <td> 
      {{data.differenceData}} 
     </td> 
    </tr> 
    [...] 

Wenn Sie verstehen wollen, wie die Arbeit Tive, ich diesen Artikel empfehlen würde Lösung könnte sein:

$scope.getDifferences = function() { 
    $scope.dataDifferenceArray.length = 0; // here ---- 
    var i; 
    for (i = 0; i < 20 ;i++) { 
    $scope.dataDifferenceArray.push({ 
     name : 30, 
     startData : 20, 
     endData : 2, 
     differenceData : 30 
    }) 
    } 
} 

aber in dieser Lösung müssen Sie das Array außerhalb (und auf einmal ly): $scope.dataDifferenceArray = [];

Edit2: Meine Antwort war nicht wirklich klar, wollen wir versuchen zu verstehen, was in tiefen passiert:

Q:Warum die ng-repeat noch die Referenz Regelwerk1 hat ?

Sie müssen daran denken, dass nicht nur 1 Bereich in Ihrer Vorlage ist.

ZB: Die ng-repeat Direktive erstellt neue Bereiche für jedes der wiederholten Elemente, aber wir können immer noch auf den übergeordneten Bereich in jedem untergeordneten Bereich zugreifen. Angular hat dieses Verhalten unter Verwendung von Prototypvererbung implementiert: Jeder untergeordnete Bereich erbt die Eigenschaften seines übergeordneten Bereichs dank seines Prototyps.

Sie können experimentieren, wie es funktioniert, indem Sie eines auf Ihren untergeordneten Elementen untersuchen und dann in die Konsole eingeben: $($0).scope() (es gibt Ihnen den Bereich des ausgewählten Elements, $0 ist das ausgewählte Element (Chrome)). Sie können jetzt sehen, dass das gleiche Objekt in $($0).scope().$parent und $($0).scope().__proto__ ist, es ist Ihr übergeordneter Bereich.

Aber es gibt ein Problem mit Prototypvererbung: Lassen Sie uns sagen, dass wir A = {}; B = {C: 1} haben, wenn A erbt von B dann A.C == 1. Aber wenn wir einen neuen Wert A.C = 2 beeinflussen, haben wir nicht geändert B, nur A.

Winkelausdrücke werden mit dem aktuellen Gültigkeitsbereich als this ausgewertet.Also, wenn wir etwas wie ng-click="dataDifferenceArray = []" haben, ist es äquivalent zu this.dataDifferenceArray = [] mit this der Bereich des Elements ist, wo ng-click ist.

Dieses Problem ist gelöst, wenn Sie Controller-als verwenden, da es den Controller in den Bereich injiziert und Sie nie eine Eigenschaft direkt auf den Bereich auswirken.

unser Beispiel Lassen Sie zurücknehmen: A = {}; B = {C: {D: 1}}, wenn A erbt von B dann A.C.D == 1. Und jetzt, auch wenn wir einen neuen Wert A.C.D = 2 beeinflussen, änderten wir B auch.

+0

@AntoineEsteve, vielen Dank für die Erklärung, können Sie erklären, warum es in diesem PLNKR funktioniert? Hier aktualisiere ich auch die Referenz, ich dachte, es sollte nicht funktionieren, aber ... http://plnkr.co/edit/7atCfQAnTbikUaGtgYi8?p=preview –

+1

@huanfeng In Ihrem PLNKR überschreiben Sie nicht die 'Liste' in einem Kindbereich. Sie haben nur 2 Scope-Level: den Controller und die 'ng-repeat'-Childs; und du aktualisierst die "liste" im selben umfang (die des controllers), die du benutzt hast, um sie zu instanziieren. Es gibt also kein Prototyp-Vererbungsproblem: Sie aktualisieren die gleiche Objekteigenschaft wie zuvor (das gleiche $ scope-Objekt). Der Ausdruck "i in list" löst sich immer noch wie gewünscht. –

0

Eigentlich sieht es so aus, als ob Ihr Array in der Click-Funktion leer ist. Dies funktioniert, wenn Sie Ihren Array-Bereich außerhalb der Funktion verschieben.

Beispiel

// Declared outside 
$scope.dataDifferenceArray = []; 

// Your function 
$scope.getDifferences = function() { 
    var i; 
    for (i = 0; i < 20 ;i++) { 
    $scope.dataDifferenceArray.push({ 
     name : 30, 
     startData : 20, 
     endData : 2, 
     differenceData : 30 
    }); 
    } 
}; 
11

selbst wenn sie richtig die Array-Referenz zu aktualisieren, war ich das gleiche Problem, ng-repeat wurde meine Änderungen nicht machen. Schließlich habe ich die Lösung gefunden, indem ich $ scope aufgerufen habe. $ Apply();

$window.wizard.on("readySubmit", function() { 
      var newArray = GenesisFactory.GetPermissionsFromTemplate(GenesisFactory.SecurityModules, true); 
      $scope.NewSecurityProfileInstance.Permission.length = 0; 
      newArray.forEach(function (entry) { 
       $scope.NewSecurityProfileInstance.Permission.push(entry); 
      }); 
      $scope.$apply(); 
     }); 

Ich hoffe, das kann helfen.

+2

$ scope. $ Apply(); ist für mich gearbeitet danke #Oswaldo –

+0

'$ scope. $ apply();' rettete meinen Tag – Bishan

2

Ich habe nichts getan, aber hinzugefügt, um diese Linie "Umfang $. $ Apply()" nach dem Element gedrückt wird, und ich bin fertig.

1

Für diejenigen, die ein Array haben im Rahmen gesetzt wird (dh $scope.$apply() verursacht einen Fehler, wenn nach einem Push genannt), aber es ist noch nicht richtig auf dem DOM aktualisieren, meine Abhilfe diese Funktion sofort rufen wurde nach die Push/Scheibe/array Update:

function applyArray(container, key) { 
    setTimeout(function() { 
     var tempArray = container[key]; 
     container[key] = []; 
     $scope.$apply(); 
     container[key] = tempArray; 
     $scope.$apply(); 
    }, 0); 
} 

von in container und key vorbei, wo container in diesem Fall würde $scope und key"dataDifferenceArray" (man beachte die Anführungszeichen) sein würde.

Ich habe keine Ahnung, warum das DOM in einigen Fällen nicht korrekt aktualisiert. Es zeigt die korrekte Anzahl von Elementen an und es wird aktualisiert, wenn ein neues Element hinzugefügt wird, es aktualisiert das DOM des untergeordneten Elements nicht korrekt (d. H. Das neu gestoßene Element kann die DOM-Ansicht des vorherigen untergeordneten Elements übernehmen). Dies könnte daran liegen, wie wir this zu vm in Johnpapa's Angular Style Guide neu definieren, aber ich bin nicht davon überzeugt.