2013-02-20 29 views
7

Tôi đang gặp sự cố mà tôi muốn liên kết với đầu ra của một hàm bên trong vòng lặp ng lặp lại. Tôi thấy rằng chức năng này được gọi hai lần cho mỗi mục thay vì một lần như tôi mong đợi. Dưới đây là phần ng-repeat (chú ý gọi calcRowTotal() ở cuối):Chức năng được gọi nhiều lần trong AngularJS Lặp lại mục

<tr ng-repeat="row in timesheetRows"> 
    <td> 
     <select ng-model="row.categoryID"> 
      <option ng-repeat="category in categories" value="{{category.id}}"> 
       {{category.title}} 
      </option> 
     </select> 
    </td> 
    <td ng-repeat="day in row.dayValues"> 
     <input type="text" ng-model="day.hours" /> 
    </td> 
    <td>{{calcRowTotal($index, row)}}</td> 
</tr> 

Các calcRowTotal() chức năng được hiển thị bên cạnh:

$scope.calcRowTotal = function (index, row) { 
    console.log('calcRowTotal - Index: ' + index); 
    var total = 0; 
    for (var i = 0; i < row.dayValues.length; i++) { 
     var num = parseFloat(row.dayValues[i].hours); 
     if (isNaN(num)) { 
      num = 0; 
      //this.dayValues[i].hours = 0; 
     } 
     total += num; 
    } 
    //updateDayTotals(); 
    return total; 
} 

Một ví dụ về một trong những mặt hàng được lặp qua được hiển thị bên cạnh:

{ 
    categoryID: 2, 
    dayValues: [ 
        { day: $scope.days[0], hours: 5 }, 
        { day: $scope.days[1], hours: 0 }, 
        { day: $scope.days[2], hours: 3 }, 
        { day: $scope.days[3], hours: 0 }, 
        { day: $scope.days[4], hours: 2 }, 
        { day: $scope.days[5], hours: 5 }, 
        { day: $scope.days[6], hours: 8 } 
    ] 
} 

tôi nhìn thấy sau trong giao diện điều khiển (hai mặt hàng này hiện trong bộ sưu tập tôi đang Looping qua):

calcRowTotal - Index: 0 
calcRowTotal - Index: 1 
calcRowTotal - Index: 0 
calcRowTotal - Index: 1 

Tôi chắc chắn có thể tạo thuộc tính "rowTotal" nhưng muốn gắn kết với dữ liệu "trực tiếp" được cung cấp bởi hàm được hiển thị ở trên. Hy vọng rằng sự trùng lặp là một cái gì đó đơn giản tôi đang mất tích vì vậy tôi đánh giá cao bất kỳ thông tin phản hồi về lý do tại sao tôi nhìn thấy sự trùng lặp. Là một lưu ý phụ, vì dữ liệu trong một trong các hộp văn bản thay đổi, tôi cần phải cập nhật tổng số hàng cũng vì vậy có thể tôi cần một cách tiếp cận khác. Quan tâm đến sự hiểu biết tình hình cụ thể này đầu tiên mặc dù .... chắc chắn không muốn sao chép vì có thể có rất nhiều hàng tiềm năng.

Dưới đây là một ví dụ: http://jsfiddle.net/dwahlin/Y7XbY/2/

+0

Đây là bản sao của http://stackoverflow.com/q/14973792/259038, mặc dù nó có thể không rõ ràng ngay lập tức. –

+0

Cảm ơn Josh. Đã dành khá nhiều thời gian để tìm kiếm nhưng không thấy điều đó. Đánh giá cao thông tin. –

+0

Vâng, đây chắc chắn không phải là loại "xóa" trùng lặp vì không rõ ràng là chúng giống nhau. Tôi chỉ muốn đóng vòng lặp cho người xem trong tương lai. –

Trả lời

13

Đó là bởi vì bạn đang liên kết với một biểu hiện chức năng ở đây:

<td>{{calcRowTotal($index, row)}}</td> 

gì mà nó buộc chức năng đó để được đánh giá lại trên tất cả các mặt hàng, trên mỗi tiêu hóa. Những gì bạn sẽ muốn làm để ngăn chặn đó là tính toán trước giá trị đó và đặt nó trong mảng của bạn để bắt đầu.

Một cách để làm điều đó là để thiết lập một chiếc đồng hồ trên mảng của bạn:

$scope.$watch('timesheetRows', function(rows) { 
    for(var i = 0; i < value.length; i++) { 
    var row = rows[i]; 
    row.rowTotal = $scope.calcRowTotal(row, i); 
    } 
}, true); 

Sau đó, tất cả các bạn phải làm là ràng buộc với giá trị mới:

<td>{{row.rowTotal}}</td> 
+0

Cảm ơn blesh - đã không nhận ra nó sẽ làm điều đó nhưng nó có ý nghĩa. –

+0

Thành thật mà nói có lẽ không phải là "một vấn đề lớn". Vì đó là ứng dụng phía máy khách và chỉ có một người dùng, nếu không gây ra vấn đề về hiệu suất, bạn có thể thoát khỏi nó nếu bạn dễ dàng duy trì. Bất kể, tôi có một số mã psuedo cho một sửa chữa đề xuất trong câu trả lời của tôi. –

+0

+1 Nhưng tại sao bạn không sử dụng 'angular.forEach' ở đây? Có vẻ như nó có thể đã cắt mã xuống một chút. Ngoài ra, bạn nên đề cập đến các biểu thức đó sẽ được gọi là * ít nhất một lần * trong mỗi lần tiêu hóa và chúng tôi không thể đảm bảo bao nhiêu lần. –

0

tôi thực sự đã có một vấn đề tương tự gần đây.

Đã kết thúc lặp qua từng đối tượng phụ và liên kết tổng số với một mô hình. Không nên là một vấn đề, đặc biệt nếu bạn chỉ sử dụng tổng số cho mục đích hiển thị.

ví dụ:

// Reset to Zero 
$scope.rowTotal = 0; 

jquery.each($scope.row, function(key, value) { 
$scope.totalRow += value.hours; 
}); 

và lặp qua từng hàng.

+4

Nhiều dự án AngularJS không sử dụng jQuery, nhưng chúng có thể sử dụng 'angular.forEach' tương tự về chức năng. –

1

Hoàn toàn vì bạn đang ràng buộc với một biểu thức hàm như @Ben Lesh đề xuất. Bằng cách nào đó bằng cách sử dụng $ xem cũng đã cho tôi thực hiện chức năng tương tự hai lần. Giải pháp để tránh thực thi kép mà chúng tôi đã sử dụng là sử dụng ng-init cho cuộc gọi hàm. Đơn giản chỉ cần tạo ra một biến init với chức năng quay trở lại như giá trị và sử dụng trong biểu ur như sau:

<tr ng-repeat="row in timesheetRows" ng-init="rowTotalValue=calcRowTotal($index, row)"> 
<td> 
    <select ng-model="row.categoryID"> 
     <option ng-repeat="category in categories" value="{{category.id}}"> 
      {{category.title}} 
     </option> 
    </select> 
</td> 
<td ng-repeat="day in row.dayValues"> 
    <input type="text" ng-model="day.hours" /> 
</td> 
<td>{{rowTotalValue}}</td> 

này làm việc cho tôi, nơi tôi đã đi qua một thuộc tính duy nhất của hàng. Không thử với chỉ số $ mặc dù. Nhưng tôi cho rằng nó sẽ hoạt động.

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