एनजी-दोहराने के साथ एक फ़ंक्शन द्वारा लौटाए गए आइटम के माध्यम से लूप कैसे करें?


114

मैं बार-बार divs बनाना चाहता हूं, आइटम एक फ़ंक्शन द्वारा लौटाए गए आइटम हैं। हालांकि निम्नलिखित कोड रिपोर्ट त्रुटियां: 10 $ डाइजेस्ट () पुनरावृत्तियों पर पहुंच गईं। निरस्त किया जा रहा! jsfiddle यहां है: http://jsfiddle.net/BraveOstrich/awnqm/

<body ng-app>
  <div ng-repeat="entity in getEntities()">
    Hello {{entity.id}}!
  </div>
</body>

जवाबों:


195

संक्षिप्त उत्तर : क्या आपको वास्तव में ऐसे फ़ंक्शन की आवश्यकता है या आप संपत्ति का उपयोग कर सकते हैं? http://jsfiddle.net/awnqm/1/

लंबा जवाब

सादगी के लिए मैं केवल आपके मामले का वर्णन करूंगा - वस्तुओं की सरणी के लिए ngRepeat। इसके अलावा, मैं कुछ विवरण छोड़ दूँगा।

AngularJS परिवर्तनों का पता लगाने के लिए गंदी जाँच का उपयोग करता है । जब आवेदन शुरू किया जाता है तो यह उसके लिए चलता $digestहै $rootScopeगुंजाइश की पदानुक्रम के$digest लिए गहराई-पहला ट्रैवर्सल करेंगे । सभी स्कोप में घड़ियों की सूची है। प्रत्येक घड़ी का अंतिम मूल्य (शुरू में ) होता है। सभी घड़ियों के लिए प्रत्येक गुंजाइश के लिए इसे चलाता है, वर्तमान मूल्य प्राप्त करता है ( ) और इसकी तुलना करता है । के बराबर हैं वर्तमान मूल्य नहीं है (पहले की तुलना हमेशा के लिए) सेट करने के लिए । जब सभी स्कोप को संसाधित किया जाता है यदि एक और गहराई-पहले ट्रैवर्सल शुरू होता है । समाप्त होता है जब गंदे == गलत या ट्रैवर्सल्स की संख्या == 10. बाद के मामले में, त्रुटि "10 $ डाइजेस्ट ()) तक पहुंच गई।" लॉग इन किया जाएगा।initWatchVal$digestwatch.get(scope)watch.lastwatch.last$digestdirtytruedirty == true $digest$rootScope$digest

अब के बारे में ngRepeat। प्रत्येक के लिए watch.getकॉल यह संग्रह से (का मान लौटने वस्तुओं को संग्रहीत करता है getEntitiesकैश में) अतिरिक्त जानकारी के साथ ( HashQueueMapसे hashKey)। हर watch.getकॉल के ngRepeatलिए hashKeyकैश से ऑब्जेक्ट प्राप्त करने की कोशिश करता है । यदि यह कैश में मौजूद नहीं है, तो इसे कैश में ngRepeatस्टोर करता है, नया स्कोप बनाता है, उस पर ऑब्जेक्ट डालता है, DOM एलिमेंट बनाता है, आदि

अब के बारे में hashKey। आमतौर hashKeyपर यूनिक नंबर जनरेट होता है nextUid()। लेकिन यह फ़ंक्शन हो सकता हैhashKeyभविष्य के उपयोग के लिए उत्पन्न करने के बाद वस्तु में संग्रहीत किया जाता है।

आपका उदाहरण त्रुटि क्यों उत्पन्न करता है : फ़ंक्शन getEntities()हमेशा नई वस्तु के साथ सरणी देता है। यह ऑब्जेक्ट नहीं है hashKeyऔर ngRepeatकैश में मौजूद नहीं है । इसलिए ngRepeatप्रत्येक पर watch.getइसके लिए नई घड़ी के साथ नई गुंजाइश उत्पन्न करता है {{entity.id}}। यह घड़ी पहले watch.getहै watch.last == initWatchVal। तो watch.get() != watch.last। तो $digestशुरू होता है नया तेवर। इसलिए ngRepeatनई घड़ी के साथ नया दायरा बनाता है। तो ... 10 ट्रैवर्स के बाद आपको त्रुटि मिलती है।

आप इसे कैसे ठीक कर सकते हैं

  1. हर getEntities()कॉल पर नए ऑब्जेक्ट न बनाएं ।
  2. यदि आपको नई वस्तुएं बनाने की आवश्यकता है तो आप hashKeyउनके लिए विधि जोड़ सकते हैं । उदाहरण के लिए इस विषय को देखें ।

आशा है कि जो लोग AngularJS के इंटर्नल को जानते हैं वे मुझे सही करेंगे अगर मैं किसी चीज में गलत हूं।


4
इसके लिए +1 धन्यवाद। मेरे पास एक ही मुद्दा था और इसके लिए एक स्थिर संपत्ति का उपयोग नहीं कर सकता था। $ $ हैशके को वास्तव में मैन्युअल IMO के ngRepeat पेज पर प्रलेखित किया जाना चाहिए।
माइकल मौसा

कोई भी विचार जो 1.1.3 से बदलकर 1.1.4 हो गया, जिसने इसे प्रभावित किया? 1.1.4 से पहले यह वास्तव में काम करता था। इसके बारे में चैंज में कुछ नहीं है और मैं यह नहीं बता सकता कि क्या अंतर है। वर्तमान व्यवहार समझ में आता है।
m59

इसके अलावा, अगर आप यह कर सकते हैं तो देखें: stackoverflow.com/questions/20933261/… मुझे यकीन नहीं है कि मेरा जवाब जाने का रास्ता है या नहीं ..
m59

2
तो Do not create new objects on every getEntities() call.यह करने के लिए सिफारिश के बाद इस तरह बहुत आसानी से तय किया जा सकता है:<div ng-repeat="entity in entities = (entities || getEntities())">
przno

2
मेरी पिछली टिप्पणी से समाधान उस स्थिति में काम करता है जब getEntities()हमेशा एक ही सरणी देता है, यदि सरणी कभी बदलती है, तो आपको यह नहीं मिलेगाng-repeat
przno

44

दोहराने के बाहर सरणी को आरम्भ करें

<body ng-app>
   <div ng-init="entities = getEntities()">
       <div ng-repeat="entity in entities">
           Hello {{entity.id}}!
       </div>
   </div>
</body>

8
यदि getEntities()प्रोग्राम के जीवनचक्र में कुछ अलग रिटर्न देता है तो यह काम नहीं करता है । उदाहरण के लिए, कहिए कि getEntities()ट्रिगर एक $http.get। जब अंत में समाधान हो जाता है (आपने AJAX कॉल किया है), entitiesपहले से ही आरंभिक होगा।
रात

3
कोणीय डॉक्स सेThe only appropriate use of ngInit is for aliasing special properties of ngRepeat. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.
Blowsie

मुझे लगता है कि मुख्य मुद्दा "दोहराने के बाहर सरणी को इनिशियलाइज़ करना है" जो कुछ भी मतलब है ... और @ नाइटो वादों पर अच्छी कॉल
Mwayi

15

यह यहां बताया गया था और यह प्रतिक्रिया मिली:

आपका गेटटर आदर्श नहीं है और मॉडल को बदलकर (हर बार जब इसे बुलाया जाता है तो एक नया सरणी बनाकर)। यह कोणीय को इस उम्मीद में बुलाता रहता है कि मॉडल आखिरकार स्थिर हो जाएगा, लेकिन यह ऐसा कभी नहीं करता है कि कोणीय एक अपवाद छोड़ देता है और फेंकता है।

गेटर रिटर्न के मूल्य समान हैं लेकिन समान नहीं हैं और यही समस्या है।

यदि आप मुख्य नियंत्रक के बाहर सरणी को स्थानांतरित करते हैं, तो आप इस व्यवहार को दूर जाते देख सकते हैं:

var array = [{id:'angularjs'}];
function Main($scope) {
    $scope.getEntities = function(){return array;};
};

क्योंकि अब वह हर बार उसी वस्तु को वापस कर रहा है। आपको किसी फ़ंक्शन के बजाय स्कोप पर गुण का उपयोग करने के लिए अपने मॉडल को फिर से आर्किटेक्ट करने की आवश्यकता हो सकती है:

हमने इसके लिए नियंत्रक की विधि के परिणाम को एक संपत्ति में निर्दिष्ट करके और एनजी कर के चारों ओर काम किया: इसके खिलाफ दोहराएं।


संपत्ति का उपयोग करना एकमात्र तरीका हो सकता है यदि फ़ंक्शन में प्रत्येक पुनरावृत्ति पर पैरामीटर बदल रहा हो।
स्टीफन

7

@Przno टिप्पणी के आधार पर

<body ng-app>
  <div ng-repeat="item in t = angular.equals(t, getEntities()) ? t : getEntities()">
    Hello {{item.id}}!
  </div>
</body>

BTW दूसरा समाधान @Artem Andreev का सुझाव है कि कोणीय 1.1.4 और अधिक में काम नहीं कर रहा है, जबकि पहले एक समस्या का समाधान नहीं करता है। इसलिए, मुझे अब डर है कि कार्यक्षमता में कमी के बिना यह कम नुकीला समाधान है


आप आइटम का मतलब है। यदि आप का मतलब क्या है, तो क्या आप समझा सकते हैं? बहुत धन्यवाद!
गेरफ्रीड

हाँ आप सही हैं। Item.idयह वही है जो बी होना चाहिए। धन्यवाद
Agat
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.