2013-02-20 18 views
7

में कई टाइम्स कॉल किए गए फ़ंक्शन को मैं एक ऐसे मुद्दे में चला रहा हूं जहां मैं एनजी-दोहराना लूप के अंदर फ़ंक्शन के आउटपुट से जुड़ना चाहता हूं। मुझे लगता है कि फ़ंक्शन को प्रति आइटम दो बार बुलाया जा रहा है, जैसा कि मैं अपेक्षा करता हूं।एंगुलरजेएस दोहराया गया अनुभाग

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

calcRowTotal() फ़ंक्शन आगे दिखाई देता है:: यहाँ एनजी-दोहराने धारा (नोटिस अंत में calcRowTotal() कॉल) है

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

आइटम आवर्ती जा रहा है में से एक का एक उदाहरण के माध्यम से आगे दिखाई देता है:

{ 
    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 } 
    ] 
} 

मैं कंसोल में निम्नलिखित (दो आइटम संग्रह मैं के माध्यम से पाशन कर रहा हूँ में हैं) दिखाई दे रही है:

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

मैं निश्चित रूप से "पंक्ति कुल" संपत्ति बना सकता हूं लेकिन ऊपर दिखाए गए फ़ंक्शन द्वारा प्रदान किए गए "लाइव" डेटा से जुड़ना पसंद करूंगा। उम्मीद है कि नकल कुछ आसान है जो मुझे याद आ रही है, इसलिए मैं किसी भी प्रतिक्रिया की सराहना करता हूं कि मैं नकल क्यों देख रहा हूं। एक साइड नोट के रूप में, जैसा कि टेक्स्टबॉक्स में से किसी एक में डेटा बदलता है, मुझे पंक्ति योग को भी अपडेट करने की आवश्यकता होती है, इसलिए मुझे एक अलग दृष्टिकोण की आवश्यकता हो सकती है। हालांकि इस विशेष स्थिति को समझने में दिलचस्पी है .... निश्चित रूप से डुप्लिकेशंस नहीं चाहते हैं क्योंकि संभावित रूप से बहुत सारी पंक्तियां हो सकती हैं।

यहाँ एक उदाहरण है: http://jsfiddle.net/dwahlin/Y7XbY/2/

+0

यह http://stackoverflow.com/q/14973792/259038 का डुप्लिकेट है, हालांकि यह तुरंत स्पष्ट नहीं हो सकता है। –

+0

धन्यवाद जोश। काफी समय खोज कर बिताया लेकिन उसे नहीं देखा। जानकारी की सराहना करें। –

+0

हाँ, यह निश्चित रूप से एक "डुप्लिकेट" को डुप्लिकेट नहीं है क्योंकि यह स्पष्ट नहीं है कि वे एक ही मामले हैं। मैं बस भविष्य के दर्शकों के लिए लूप बंद करना चाहता था। –

उत्तर

13

क्योंकि आप एक समारोह अभिव्यक्ति यहाँ के लिए बाध्य कर रहे हैं यह है:

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

क्या है कि यह है कि समारोह के लिए मजबूर करता है, हर आइटम पर पुनः मूल्यांकन के लिए हर डाइजेस्ट पर। इससे पहले कि आप इसे रोकने के लिए क्या करना चाहते हैं, उस मान को पूर्व-गणना करें और इसे शुरू करने के लिए अपने सरणी में रखें।

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

फिर तुम सब करने की है कि नए मूल्य के लिए बाँध है:

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

धन्यवाद ब्लेश - यह नहीं पता था कि यह ऐसा करेगा लेकिन यह समझ में आता है। –

+0

यह ईमानदारी से शायद "बड़ा सौदा" नहीं है। चूंकि यह क्लाइंट साइड ऐप है, और केवल एक उपयोगकर्ता है, यदि यह प्रदर्शन समस्याओं का कारण नहीं बना रहा है, तो आप इसे छोड़ सकते हैं यदि आपके लिए बनाए रखना आसान है। भले ही, मेरे पास मेरे उत्तर में एक प्रस्तावित फिक्स के लिए कुछ psuedo-code है। –

+0

+1 लेकिन आपने यहां 'angular.forEach' का उपयोग क्यों नहीं किया? ऐसा लगता है कि यह कोड को थोड़ा सा घटा सकता है। साथ ही, आपको यह उल्लेख करना चाहिए कि प्रत्येक पाचन के दौरान अभिव्यक्ति * कम से कम एक बार * कहा जाएगा और हम कितनी बार गारंटी नहीं दे सकते। –

0

मैं वास्तव में एक था

एक तरीका यह है कि ऐसा करने के लिए अपने सरणी पर नजर स्थापित करने के लिए है हाल ही में इसी तरह की समस्या।

प्रत्येक उप-ऑब्जेक्ट के माध्यम से पुनरावृत्ति समाप्त हो गया और कुल मिलाकर मॉडल को बाध्यकारी कर दिया गया। कोई मुद्दा नहीं होना चाहिए, खासकर यदि आप केवल प्रदर्शन उद्देश्यों के लिए कुल उपयोग कर रहे हैं।

उदाहरण के लिए।

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

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

और प्रत्येक पंक्ति के माध्यम से पुनरावृत्त करें।

+4

कई AngularJS प्रोजेक्ट jQuery का उपयोग नहीं करते हैं, लेकिन वे कार्यात्मक रूप से समान 'कोणीय .forEach' का उपयोग कर सकते हैं। –

1

यह पूरी तरह से है क्योंकि आप फ़ंक्शन अभिव्यक्ति के लिए बाध्यकारी हैं क्योंकि @ बेन लश ने सुझाव दिया था। किसी भी तरह से $ घड़ी का उपयोग करने से मुझे एक ही समारोह को दो बार निष्पादित कर दिया गया। हमारे द्वारा उपयोग किए जाने वाले डबल निष्पादन से बचने के लिए समाधान फ़ंक्शन कॉल के लिए एनजी-इनिट का उपयोग करके किया जाता है। आप मूल्य के रूप में समारोह वापसी के साथ एक init चर बना सकते हैं और उपयोग करें कि नीचे के रूप में उर अभिव्यक्ति में:

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

यह मेरे लिए काम किया, जहां मैं पंक्ति की एक एकल विशेषता गुजर रहा था। यद्यपि $ सूचकांक के साथ कोशिश नहीं की। लेकिन मुझे लगता है कि यह काम करना चाहिए।