2015-04-24 27 views
30

Tôi đang kết xuất dữ liệu thông qua chu trình ng-lặp lại. Và tôi muốn nó cập nhật khi tôi cập nhật mảng. Từ những gì tôi đọc này sẽ xảy ra tự động tuy nhiên điều này không hoạt động. Vậy tôi đang làm gì sai?ng-repeat không cập nhật khi cập nhật mảng

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 (chức năng này được kích hoạt vào một nút với ng nhấp chuột):

$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 cho thấy mảng được cập nhật một cách chính xác, tuy nhiên bảng trong quan điểm của tôi không thay đổi. Tôi không biết mình đang làm gì sai.

+2

Bất kỳ lỗi nào trong bảng điều khiển? Bạn có thể sao chép trong một plunkr? – tymeJV

+1

html của bạn có bị ràng buộc chính xác với bộ điều khiển không? – illiptic

Trả lời

46

Đó là vì bạn thay đổi tham chiếu mảng trong phương thức getDifferences của mình.

Để tránh điều đó, chúng tôi dot, ví dụ với "bộ điều khiển là" cú pháp:

<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> 
    [...] 

Nếu bạn muốn hiểu thế nào phạm vi công việc, tôi sẽ tư vấn bài viết này: https://github.com/angular/angular.js/wiki/Understanding-Scopes#ngRepeat

Một giải pháp có thể là:

$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 
    }) 
    } 
} 

nhưng trong giải pháp này, bạn cần tạo mảng bên ngoài (và bật ly một lần): $scope.dataDifferenceArray = [];

Edit2: câu trả lời của tôi là không thực sự rõ ràng, chúng ta hãy cố gắng hiểu những gì đang xảy ra ở vùng sâu:

Q:Tại sao ng-repeat vẫn có REFERENCE1 tài liệu tham khảo ?

Bạn phải nhớ rằng không chỉ có 1 phạm vi trong mẫu của bạn.

Ví dụ: chỉ thị ng-repeat tạo phạm vi mới cho từng yếu tố lặp lại, nhưng chúng tôi vẫn có thể truy cập vào phạm vi gốc trong mỗi phạm vi con. Góc thực hiện hành vi này bằng cách sử dụng Thừa kế nguyên mẫu: mỗi phạm vi con kế thừa các thuộc tính của phạm vi gốc nhờ nguyên mẫu của nó.

Bạn có thể thử nghiệm cách hoạt động bằng cách kiểm tra một yếu tố con, sau đó nhập vào bảng điều khiển: $($0).scope() (nó sẽ cung cấp cho bạn phạm vi của phần tử đã chọn, $0 là phần tử đã chọn (Chrome)). Bây giờ bạn có thể thấy rằng có cùng một đối tượng trong số $($0).scope().$parent$($0).scope().__proto__, đó là phạm vi cha mẹ của bạn.

Nhưng có một vấn đề với kế thừa mẫu thử nghiệm: Giả sử chúng tôi có A = {}; B = {C: 1}, nếu A được kế thừa từ B thì A.C == 1. Nhưng nếu chúng tôi ảnh hưởng đến một giá trị mới A.C = 2, chúng tôi đã không thay đổi B, chỉ A.

Biểu thức góc được đánh giá bằng phạm vi hiện tại là this.Vì vậy, nếu chúng tôi có một cái gì đó như ng-click="dataDifferenceArray = []", nó tương đương với this.dataDifferenceArray = [] với this là phạm vi của phần tử trong đó ng-click là.

Vấn đề này được giải quyết khi bạn đang sử dụng điều khiển-như vì nó bơm bộ điều khiển trong phạm vi và bạn sẽ không bao giờ trực tiếp ảnh hưởng đến thuộc tính đến phạm vi.

Hãy lấy lại ví dụ của chúng tôi: A = {}; B = {C: {D: 1}}, nếu A được kế thừa từ B thì A.C.D == 1. Và bây giờ ngay cả khi chúng tôi ảnh hưởng đến một giá trị mới A.C.D = 2, chúng tôi cũng đã thay đổi B.

+0

@AntoineEsteve, cảm ơn bạn đã giải thích, bạn có thể giúp giải thích lý do tại sao nó hoạt động trong plnkr này? Ở đây tôi cũng cập nhật các tài liệu tham khảo, tôi nghĩ rằng nó không nên làm việc, nhưng ... http://plnkr.co/edit/7atCfQAnTbikUaGtgYi8?p=preview –

+1

@huanfeng Trong plnkr của bạn, bạn đã không ghi đè lên 'danh sách' trong một phạm vi con. Bạn chỉ có 2 mức phạm vi: bộ điều khiển và các nút con 'ng-repeat'; và bạn đang cập nhật 'danh sách' trong cùng phạm vi (bộ điều khiển) mà bạn đã sử dụng để khởi tạo nó. Vì vậy, không có vấn đề thừa kế nguyên mẫu: bạn đang cập nhật thuộc tính đối tượng tương tự hơn trước (cùng một đối tượng '$ scope'). Biểu thức 'i trong danh sách' vẫn giải quyết như bạn muốn. –

0

Thực ra có vẻ như mảng của bạn đang được đặt thành rỗng bên trong hàm nhấp chuột. Điều này sẽ làm việc nếu bạn di chuyển phạm vi mảng của bạn bên ngoài hàm.

Ví dụ

// 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

ngay cả khi cập nhật đúng cách tham chiếu mảng, tôi đã có cùng một vấn đề, ng-repeat không render thay đổi của tôi. Cuối cùng tôi tìm thấy giải pháp bằng cách gọi tới $ scope. $ 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(); 
     }); 

Tôi hy vọng điều này có thể hữu ích.

+2

$ scope. $ Apply(); được làm việc cho tôi cảm ơn bạn #Oswaldo –

+0

'$ scope. $ apply();' đã lưu ngày của tôi – Bishan

2

Tôi đã không làm gì nhưng nói thêm dòng này "$ phạm vi. $ Apply()" sau khi đẩy phần tử, và tôi đang thực hiện.

1

Đối với những người có một mảng được thiết lập trong phạm vi (ví dụ: $scope.$apply() gây ra một lỗi nếu gọi sau một push), nhưng nó là vẫn không cập nhật chính xác trên DOM, workaround tôi đã gọi chức năng này ngay sau khi cập nhật push/miếng/mảng:

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

Bằng cách vượt qua trong containerkey, nơi container trong trường hợp này sẽ là $scopekey sẽ "dataDifferenceArray" (lưu ý có dấu ngoặc kép).

Tôi không biết tại sao DOM không cập nhật chính xác trong một số trường hợp. Nó cho thấy số lượng phần tử chính xác và cập nhật khi thêm phần tử mới, nó chỉ không cập nhật chính xác phần tử con DOM (tức là phần tử mới được đẩy có thể có trên chế độ xem DOM của trẻ trước đó). Điều này có thể là do cách chúng tôi xác định lại this đến vm trong Johnpapa's Angular Style Guide, nhưng tôi không tự tin về điều đó.

Các vấn đề liên quan