एंगुलरज में एरे को कैसे देखें?


320

मेरे दायरे में वस्तुओं की एक सरणी है, मैं प्रत्येक वस्तु के सभी मूल्यों को देखना चाहता हूं।

यह मेरा कोड है:

function TodoCtrl($scope) {
  $scope.columns = [
      { field:'title', displayName: 'TITLE'},
      { field: 'content', displayName: 'CONTENT' }
  ];
   $scope.$watch('columns', function(newVal) {
       alert('columns changed');
   });
}

लेकिन जब मैं मूल्यों को संशोधित करता हूं, उदाहरण के लिए मैं बदल TITLEजाता हूं TITLE2, तो alert('columns changed')कभी भी पॉप नहीं होता है।

किसी सरणी के अंदर वस्तुओं को कैसे देखें?

एक लाइव डेमो है: http://jsfiddle.net/SYx9b/

जवाबों:


529

आप 3 तर्क सेट कर सकते हैं $watchकरने के लिए true:

$scope.$watch('data', function (newVal, oldVal) { /*...*/ }, true);

Https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watch देखें

कोणीय 1.1.x के बाद से आप संग्रह के उथले घड़ी (सिर्फ "पहले स्तर") को देखने के लिए $ घड़ी का उपयोग कर सकते हैं।

$scope.$watchCollection('data', function (newVal, oldVal) { /*...*/ });

Https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watchCollection देखें


2
angular.equalsजब तीसरा तर्क बूलियन मान लेता है तो आप क्यों उपयोग कर रहे हैं ?
JayQuerie.com

धन्यवाद ट्रेवर, डॉक्स का गलत उच्चारण। मैंने ऊपर का कोड अपडेट कर दिया है, और अपने कोड को मैच के लिए अपडेट कर दिया है।
पिरान

36
1.1.x में अब आपके पास$watchCollection
जोनाथन रोवी

39
$watchCollectionकिसी सरणी या वस्तु का केवल "प्रथम स्तर" देखेगा, जैसा कि मैं समझता हूँ। उपरोक्त उत्तर सही है यदि आपको इससे अधिक गहरी देखने की आवश्यकता है। bennadel.com/blog/…
ब्लेज़मॉन्गर

1
शानदार जवाब ... अगर मैं कर सकता तो आपको एक से अधिक वोट देता ... :) धन्यवाद
जॉनी-वाई

50

आपकी $ घड़ी में किसी वस्तु को डीप-डाइविंग करने के लिए प्रदर्शन परिणाम हैं। कभी-कभी (उदाहरण के लिए, जब परिवर्तन केवल धक्का और चबूतरे होते हैं), तो आप $ आसानी से गणना किए गए मान, जैसे कि सरणी गति देखना चाहते हैं।


1
इसके लिए अधिक वोट होने चाहिए। दीप देखना महंगा है। मैं समझता हूं कि ओपी को गहरी देखने की तलाश थी, लेकिन लोग यहां आकर जानना चाहते हैं कि क्या सरणी में ही बदलाव हुआ है। उस मामले में लंबाई देखना अधिक तेज है।
स्कॉट सिल्वी

42
यह एक टिप्पणी होनी चाहिए, एक जवाब नहीं।
ब्लेज़मॉन्गर

1
@ वॉल्ज़मॉन्जर टिप्पणी ( stackoverflow.com/questions/14712089#comment32440226_14713978 ) द्वारा उल्लिखित प्रदर्शन मुद्दों को $ watchCollection का उपयोग करके कम किया जाएगा ।
बीन

नीट सलाह। इस टिप्पणी के बारे में एक जवाब नहीं होने के बारे में, मेरी राय में एक उत्तर के लिए स्वीकृति मानदंड को पूरा करने के लिए सुझाव को विस्तृत करना बेहतर होगा। मुझे लगता है कि इस दृष्टिकोण के साथ सवाल का एक सुरुचिपूर्ण समाधान प्राप्त किया जा सकता है।
एमी पेलेग्रिनी

43

यदि आप केवल एक सरणी देखने जा रहे हैं, तो आप बस इस बिट कोड का उपयोग कर सकते हैं:

$scope.$watch('columns', function() {
  // some value in the array has changed 
}, true); // watching properties

उदाहरण

लेकिन यह कई सरणियों के साथ काम नहीं करेगा:

$scope.$watch('columns + ANOTHER_ARRAY', function() {
  // will never be called when things change in columns or ANOTHER_ARRAY
}, true);

उदाहरण

इस स्थिति को संभालने के लिए, मैं आमतौर पर उन कई सरणियों को परिवर्तित करता हूं, जिन्हें मैं JSON में देखना चाहता हूं:

$scope.$watch(function() { 
  return angular.toJson([$scope.columns, $scope.ANOTHER_ARRAY, ... ]); 
},
function() {
  // some value in some array has changed
}

उदाहरण

जैसा कि @jssebastian ने टिप्पणियों में बताया, यह JSON.stringifyबेहतर हो सकता है angular.toJsonक्योंकि यह उन सदस्यों को संभाल सकता है जो '$' से शुरू होते हैं और अन्य मामलों को भी संभव करते हैं।


मुझे यह भी पता है कि वहाँ एक 3 पैरामीटर है $watch, क्या यह वही करने में सक्षम है? Pass true as a third argument to watch an object's properties too.देखें: cheatography.com/proloser/cheat-sheets/angularjs
Freewind

@Freewind अगर कभी ऐसा कोई मामला है, जहाँ आपको कई ऐरे देखने की आवश्यकता होगी, तो यह यहाँ देखे जाने पर विफल हो जाएगा । लेकिन हाँ, यह भी काम करेगा और angular.toJsonएक ही सरणी पर उपयोग के रूप में एक ही कार्यक्षमता प्रदान करता है ।
JayQuerie.com

2
बस इस बात से सावधान रहें कि angular.toJson में '$' से शुरू होने वाले सदस्य शामिल नहीं हैं: angular.toJson ({"$ hello": "world"}) सिर्फ "{}" है। मैंने JSON.stringify () को एक विकल्प के रूप में इस्तेमाल किया
jssebastian

@ jssebastian धन्यवाद - मैंने उस जानकारी को शामिल करने के लिए उत्तर अपडेट कर दिया है।
JayQuerie.com

1
क्या हम जान सकते हैं कि कौन सी संपत्ति बदल गई है?
अश्विन

21

यह ध्यान देने योग्य है कि कोणीय 1.1.x और इसके बाद के संस्करण में, अब आप $ वॉच के बजाय $ वॉच कॉलेक्शन का उपयोग कर सकते हैं । हालांकि $ watchCollection उथली घड़ियों को बनाने के लिए प्रकट होता है, इसलिए यह ऑब्जेक्ट्स के सरणियों के साथ काम नहीं करेगा जैसे आप उम्मीद करते हैं। यह सरणी में परिवर्धन और विलोपन का पता लगा सकता है, लेकिन सरणियों के अंदर वस्तुओं के गुणों को नहीं।


5
$ watchCollection केवल उथले देखता है, हालांकि। इसलिए जैसा कि मैं इसे समझता हूं, सरणी के आइटम के गुणों को बदलना (जैसा कि प्रश्न में) घटना को ट्रिगर नहीं करेगा।
तरनचफ

3
यह एक टिप्पणी होनी चाहिए, एक जवाब नहीं।
ब्लेज़मॉन्गर

18

यहां उन 3 तरीकों की तुलना की गई है, जिन्हें आप उदाहरण के साथ एक स्कोप वैरिएबल देख सकते हैं:

$ घड़ी () इससे ट्रिगर होती है:

$scope.myArray = [];
$scope.myArray = null;
$scope.myArray = someOtherArray;

$ watchCollection () को ऊपर और नीचे की हर चीज़ से ट्रिगर किया गया है:

$scope.myArray.push({}); // add element
$scope.myArray.splice(0, 1); // remove element
$scope.myArray[0] = {}; // assign index to different value

$ घड़ी (..., सत्य) को ऊपर और नीचे से ट्रिगर किया गया है:

$scope.myArray[0].someProperty = "someValue";

बस एक और बात...

घड़ी $ () एकमात्र है जो ट्रिगर करती है जब एक सरणी को दूसरे सरणी के साथ बदल दिया जाता है, भले ही उस अन्य सरणी में एक ही सटीक सामग्री हो।

उदाहरण के लिए जहां $watch()आग $watchCollection()होगी और नहीं होगी:

$scope.myArray = ["Apples", "Bananas", "Orange" ];

var newArray = [];
newArray.push("Apples");
newArray.push("Bananas");
newArray.push("Orange");

$scope.myArray = newArray;

नीचे एक उदाहरण JSFiddle का लिंक दिया गया है जो सभी अलग-अलग घड़ी संयोजनों का उपयोग करता है और लॉग संदेश का उत्पादन करता है ताकि संकेत मिले कि "घड़ियों" को ट्रिगर किया गया है:

http://jsfiddle.net/luisperezphd/2zj9k872/


वास्तव में, निस्संदेह 'वन मोर थिंग' को नोट करने के लिए
एंडी मा

12

$ watchCollection पूरा करता है कि आप क्या करना चाहते हैं। नीचे एक उदाहरण angularjs वेबसाइट http://docs.angularjs.org/api/ng/type/$rootScope.Scope से कॉपी किया गया है , जबकि यह सुविधाजनक है, प्रदर्शन को विशेष रूप से ध्यान में रखा जाना चाहिए जब आप एक बड़े संग्रह को देखते हैं।

  $scope.names = ['igor', 'matias', 'misko', 'james'];
  $scope.dataCount = 4;

  $scope.$watchCollection('names', function(newNames, oldNames) {
     $scope.dataCount = newNames.length;
  });

  expect($scope.dataCount).toEqual(4);
  $scope.$digest();

  //still at 4 ... no changes
  expect($scope.dataCount).toEqual(4);

  $scope.names.pop();
  $scope.$digest();

  //now there's been a change
  expect($scope.dataCount).toEqual(3);

14
ओपी ने वस्तुओं की एक सरणी निर्दिष्ट की। आपका उदाहरण स्ट्रिंग की एक सरणी के साथ काम करता है, लेकिन $ watchCollection वस्तुओं की एक सरणी के साथ काम नहीं करता है।
केविनएल

4

इस समाधान ने मेरे लिए बहुत अच्छा काम किया, मैं इसे एक निर्देश में कर रहा हूं:

गुंजाइश। $ घड़ी (attrs.testWatch, function () {.....}, true);

सच बहुत अच्छी तरह से काम करता है और सभी chnages (जोड़ने, हटाने, या एक क्षेत्र को संशोधित) के लिए प्रतिक्रिया करता है।

यहाँ इसके साथ खेलने के लिए एक काम करने वाला प्लंकर है।

एंगुलरजेएस में एक ऐरे को देखना

मुझे उम्मीद है कि यह आपके लिए उपयोगी हो सकता है। यदि आपके कोई प्रश्न हैं, तो पूछने के लिए स्वतंत्र महसूस करें, मैं मदद करने की कोशिश करूंगा :)


4

मेरे मामले में, मुझे एक सेवा देखने की ज़रूरत थी, जिसमें कई अन्य नियंत्रकों द्वारा देखी जाने वाली एक पता वस्तु भी है। जब तक मैंने 'सही' पैरामीटर नहीं जोड़ा, मैं एक लूप में फंस गया था, जो वस्तुओं को देखते समय सफलता की कुंजी प्रतीत होता है।

$scope.$watch(function() {
    return LocationService.getAddress();
}, function(address) {
    //handle address object
}, true);

1

objectEqualityफ़ंक्शन के पैरामीटर (तीसरे पैरामीटर) को सेट करना $watchनिश्चित रूप से सरणी के सभी गुणों को देखने का सही तरीका है।

$scope.$watch('columns', function(newVal) {
    alert('columns changed');
},true); // <- Right here

पिरान इसका अच्छी तरह से उत्तर देता है और $watchCollectionसाथ ही उल्लेख भी करता है।

ज्यादा जानकारी

इसका कारण मैं पहले से ही उत्तर दिए गए प्रश्न का उत्तर दे रहा हूं, क्योंकि मैं यह बताना चाहता हूं कि विज़ार्डवर्ल्ड का उत्तर अच्छा नहीं है और इसका उपयोग नहीं किया जाना चाहिए।

समस्या यह है कि खुदाई तुरंत नहीं होती है। उन्हें कोड के वर्तमान ब्लॉक को पूरा करने से पहले इंतजार करना होगा। इस प्रकार, lengthएक सरणी को देखना वास्तव में कुछ महत्वपूर्ण बदलावों को याद कर सकता है जो $watchCollectionपकड़ लेंगे।

इस कॉन्फ़िगरेशन को मानें:

$scope.testArray = [
    {val:1},
    {val:2}
];

$scope.$watch('testArray.length', function(newLength, oldLength) {
    console.log('length changed: ', oldLength, ' -> ', newLength);
});

$scope.$watchCollection('testArray', function(newArray) {
    console.log('testArray changed');
});

पहली नज़र में, ऐसा लग सकता है कि ये एक ही समय में आग लगेंगी, जैसे कि इस मामले में:

function pushToArray() {
    $scope.testArray.push({val:3});
}
pushToArray();

// Console output
// length changed: 2 -> 3
// testArray changed

यह काफी अच्छा काम करता है, लेकिन इस पर विचार करें:

function spliceArray() {
    // Starting at index 1, remove 1 item, then push {val: 3}.
    $testArray.splice(1, 1, {val: 3});
}
spliceArray();

// Console output
// testArray changed

ध्यान दें कि परिणामी लंबाई समान थी भले ही सरणी में एक नया तत्व है और एक तत्व खो गया है, इसलिए जैसा $watchकि चिंतित है, lengthबदल नहीं गया है। $watchCollectionइस पर उठाया, हालांकि।

function pushPopArray() {
    $testArray.push({val: 3});
    $testArray.pop();
}
pushPopArray();

// Console output
// testArray change

एक ही परिणाम एक ही ब्लॉक में एक धक्का और पॉप के साथ होता है।

निष्कर्ष

हर प्रॉपर्टी को ऐरे में देखने के लिए, $watchऐरे इटसेल्फ पर थर्ड पैरामीटर (ऑब्जेक्विटी) को शामिल करें और सही पर सेट करें। हां, यह महंगा है लेकिन कभी-कभी जरूरी है।

यह देखने के लिए कि ऑब्जेक्ट कब दर्ज करें / बाहर निकलें, ए का उपयोग करें $watchCollection

सरणी $watchकी lengthसंपत्ति पर उपयोग न करें । लगभग कोई अच्छा कारण नहीं है जो मैं ऐसा करने के लिए सोच सकता हूं।


0

$scope.changePass = function(data){
    
    if(data.txtNewConfirmPassword !== data.txtNewPassword){
        $scope.confirmStatus = true;
    }else{
        $scope.confirmStatus = false;
    }
};
  <form class="list" name="myForm">
      <label class="item item-input">        
        <input type="password" placeholder="ใส่รหัสผ่านปัจจุบัน" ng-model="data.txtCurrentPassword" maxlength="5" required>
      </label>
      <label class="item item-input">
        <input type="password" placeholder="ใส่รหัสผ่านใหม่" ng-model="data.txtNewPassword" maxlength="5" ng-minlength="5" name="checknawPassword" ng-change="changePass(data)" required>
      </label>
      <label class="item item-input">
        <input type="password" placeholder="ใส่รหัสผ่านใหม่ให้ตรงกัน" ng-model="data.txtNewConfirmPassword" maxlength="5" ng-minlength="5" name="checkConfirmPassword" ng-change="changePass(data)" required>
      </label>      
       <div class="spacer" style="width: 300px; height: 5px;"></div> 
      <span style="color:red" ng-show="myForm.checknawPassword.$error.minlength || myForm.checkConfirmPassword.$error.minlength">รหัสผ่านต้องมีจำนวน 5 หลัก</span><br>
      <span ng-show="confirmStatus" style="color:red">รหัสผ่านใหม่ไม่ตรงกัน</span>
      <br>
      <button class="button button-positive  button-block" ng-click="saveChangePass(data)" ng-disabled="myForm.$invalid || confirmStatus">เปลี่ยน</button>
    </form>

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