एंगुलरजेएस में मॉडल परिवर्तन को देखते हुए मैं शुरुआती भार को कैसे अनदेखा कर सकता हूं?


184

मेरे पास एक वेब पेज है जो एकल इकाई के लिए संपादक के रूप में कार्य करता है, जो $ स्कोप में एक गहरे ग्राफ के रूप में बैठता है। अपने REST API ($ संसाधन के माध्यम से) के बाद मुझे एक प्रतिक्रिया मिलती है, मैं 'फ़ील्डकेंटर' में एक घड़ी जोड़ता हूं। मैं इस घड़ी का उपयोग यह जानने के लिए कर रहा हूं कि पृष्ठ / इकाई "गंदा" है या नहीं। अभी मैं सेव बटन को उछाल रहा हूं, लेकिन वास्तव में मैं सेव बटन को तब तक अदृश्य बनाना चाहता हूं, जब तक यूजर मॉडल को मैली न कर दे।

मुझे जो मिल रहा है वह घड़ी का एक ट्रिगर है, जो मुझे लगता है कि हो रहा है क्योंकि .fieldcontainer = ... असाइनमेंट मेरी घड़ी बनाने के तुरंत बाद होता है। मैं शुरुआती झूठे अलार्म को अवशोषित करने के लिए एक "डर्टीकाउंट" संपत्ति का उपयोग करने के बारे में सोच रहा था, लेकिन यह बहुत हैकिंग लगता है ... और मुझे लगा कि इससे निपटने के लिए "कोणीय मुहावरेदार" तरीका होना चाहिए - मैं केवल एक ही नहीं हूं एक गंदे मॉडल का पता लगाने के लिए एक घड़ी का उपयोग करना।

यहां वह कोड है जहां मैंने अपनी घड़ी सेट की है:

 $scope.fieldcontainer = Message.get({id: $scope.entityId },
            function(message,headers) {
                $scope.$watch('fieldcontainer',
                    function() {
                        console.log("model is dirty.");
                        if ($scope.visibility.saveButton) {
                            $('#saveMessageButtonRow').effect("bounce", { times:5, direction: 'right' }, 300);
                        }
                    }, true);
            });

मुझे लगता है कि वहाँ एक "अगर (गंदे> 0)" के साथ मेरे "UI गंदे" कोड की रक्षा करने की तुलना में यह करने के लिए एक क्लीनर तरीका हो गया है रखने के लिए ...


मुझे कुछ बटन के आधार पर $ गुंजाइश.fieldcontainer को फिर से लोड करने में सक्षम होने की आवश्यकता है (जैसे इकाई का पिछला संस्करण लोड करना)। इसके लिए मुझे घड़ी को फिर से लोड करना होगा, फिर घड़ी को फिर से शुरू करना होगा।
केविन हॉफमैन

क्या आप मेरे उत्तर को स्वीकार किए गए उत्तर को बदलने पर विचार करेंगे? जो लोग इसे नीचे पढ़ने के लिए समय लेते हैं वे इस बात से सहमत होते हैं कि यह सही समाधान है।
त्रिकटूर

@trixtur मुझे वही ओपी समस्या है, लेकिन मेरे मामले में आपका जवाब काम नहीं करता है, क्योंकि मेरा पुराना मूल्य नहीं है undefined। इसका एक डिफ़ॉल्ट मूल्य है जो मेरे मॉडल अपडेट के मामले में आवश्यक है जो सभी जानकारी के साथ नहीं आया है। इसलिए कुछ मान नहीं बदलते हैं लेकिन उन्हें ट्रिगर करना पड़ता है।
इलहोलज़

@oliholz ​​इसलिए अपरिभाषित के खिलाफ जाँच करने के बजाय, "टाइपोफ़" को बाहर निकालें और अपने डिफ़ॉल्ट मान के खिलाफ old_fieldcontainer की जाँच करें।
त्रिकटूर

@ क्वीनहॉफमैन आपको इस प्रश्न को खोजने वाले अन्य लोगों के लिए सही उत्तर पर MW के उत्तर को चिह्नित करना चाहिए। यह एक बेहतर उपाय है। धन्यवाद!
देव ०१

जवाबों:


118

प्रारंभिक भार से ठीक पहले एक ध्वज स्थापित करें,

var initializing = true

और तब जब पहली $ घड़ी आग करती है, करते हैं

$scope.$watch('fieldcontainer', function() {
  if (initializing) {
    $timeout(function() { initializing = false; });
  } else {
    // do whatever you were going to do
  }
});

ध्वज को वर्तमान पाचन चक्र के अंत में फाड़ा जाएगा, इसलिए अगला परिवर्तन अवरुद्ध नहीं होगा।


17
हां, यह काम करेगा लेकिन @MW द्वारा सुझाए गए पुराने और नए मूल्य दृष्टिकोण की तुलना करना। दोनों सरल और अधिक कोणीय मुहावरेदार है। क्या आप स्वीकृत उत्तर को अपडेट कर सकते हैं?
19

2
हमेशा पुराने फ़ायर को नए आग के बराबर स्थापित करने के लिए पहली आग पर इस ध्वज को हैक करने से बचने के लिए विशेष रूप से जोड़ा गया था
चार्ली मार्टिन

2
मेगावाट का जवाब वास्तव में गलत है क्योंकि पुराने मूल्य के नए मूल्य उस मामले को नहीं संभालेंगे जहां पुराना मूल्य अपरिभाषित है।
त्रिकटूर

1
टिप्पणीकारों के लिए: यह एक ईश्वर मॉडल नहीं है, कुछ भी आपको डेकोरेटर के दायरे में 'इनिशियलाइज्ड' वैरिएबल को रोकने के लिए नहीं रोकता है, और फिर इसके साथ अपनी "सामान्य" घड़ी को सजाने के लिए। किसी भी मामले में यह पूरी तरह से इस सवाल के दायरे से बाहर है।
फिर से लिखा

1
प्रोपोगेट विधियों की तुलना के लिए plnkr.co/edit/VrWrHHwukqnxaEM3J5i देखें , दोनों .get () कॉलबैक, और स्कोप इनिशियलाइज़ेशन में वॉचर्स सेट करना।
फिर से लिखा

483

पहली बार श्रोता को बुलाया जाता है, पुराने मूल्य और नए मूल्य समान होंगे। तो बस यह करें:

$scope.$watch('fieldcontainer', function(newValue, oldValue) {
  if (newValue !== oldValue) {
    // do whatever you were going to do
  }
});

यह वास्तव में जिस तरह से कोणीय डॉक्स इसे संभालने की सलाह देते हैं :

चौकीदार के दायरे में पंजीकृत होने के बाद, चौकीदार को आरंभ करने के लिए श्रोता fn को अतुल्यकालिक ($ evalAsync के माध्यम से) कहा जाता है। दुर्लभ मामलों में, यह अवांछनीय है क्योंकि श्रोता को कहा जाता है जब watchExpression का परिणाम नहीं बदला। श्रोता fn के भीतर इस परिदृश्य का पता लगाने के लिए, आप newVal और oldVal की तुलना कर सकते हैं। यदि ये दोनों मूल्य समान हैं (===) तो श्रोता को आरंभीकरण के कारण बुलाया गया था


3
यह तरीका @ rewritten के जवाब की तुलना में अधिक मुहावरेदार है
Ji Ví Vypřdřík

25
यह सही नहीं है। बिंदु nullप्रारंभिक लोड किए गए मान से परिवर्तन को अनदेखा कर रहा है, न कि परिवर्तन को अनदेखा करने के लिए जब कोई परिवर्तन नहीं है।
फिर से लिखा

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

ओपी विशेष रूप से संसाधनों पर नजर रखने वालों (आरईएसटी सेवाओं से) के बारे में पूछ रहा है। संसाधन पहले बनाए जाते हैं, फिर पहरेदारों ने आवेदन किया, और फिर प्रतिक्रिया से विशेषताओं को लिखा जाता है, और उसके बाद ही कोणीय एक चक्र बनाता है। "इनिशियलाइज़िंग" ध्वज के साथ पहले चक्र को छोड़ना केवल आरंभिक संसाधनों पर एक द्रष्टा को लागू करने का एक तरीका प्रदान करता है, लेकिन फिर भी / से परिवर्तन के लिए देख रहा है null
फिर से लिखा

7
यह गलत है, oldValueपहले घूमने-फिरने पर अशक्त होगा।
केविन सी।

42

मुझे पता है कि इस सवाल का जवाब दिया गया है, हालांकि मेरे पास एक सुझाव है:

$scope.$watch('fieldcontainer', function (new_fieldcontainer, old_fieldcontainer) {
    if (typeof old_fieldcontainer === 'undefined') return;

    // Other code for handling changed object here.
});

झंडे के काम का उपयोग करना, लेकिन यह आपको नहीं लगता है एक कोड गंध का एक सा है?


1
जाने का यह रास्ता है। कॉफ़ीस्क्रिप्ट में, यह return unless oldValue?(CS में मौजूद संचालक है) जितना सरल है।
केविन सी।

1
शब्द कोड गंध पर सहारा! देव वस्तु लोल भी देखें। बहुत अच्छा।
मैथ्यू हरवुड

1
हालाँकि यह स्वीकृत उत्तर नहीं है, फिर भी यह एक एपीआई से किसी वस्तु को पॉप्युलेट करते समय मेरा कोड काम करता है और मैं अलग-अलग सेव स्टेट्स देखना चाहता हूं। बहुत अच्छा।
लुकास रेपे वालैंडर

1
धन्यवाद - इसने मेरे लिए मदद की
वैंड मेकर

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

4

वर्तमान मूल्यों के प्रारंभिक लोडिंग के दौरान पुराना मूल्य क्षेत्र अपरिभाषित है। तो नीचे दिया गया उदाहरण आपको शुरुआती लोडिंग को बाहर करने में मदद करता है।

$scope.$watch('fieldcontainer', 
  function(newValue, oldValue) {
    if (newValue && oldValue && newValue != oldValue) {
      // here what to do
    }
  }), true;

आप शायद उपयोग करना चाहते हैं! == चूंकि nullऔर undefinedइस स्थिति में मेल खाएंगे, या ( '1' == 1आदि)
जॅमी पटे

सामान्य तौर पर आप सही हैं। लेकिन उस मामले में पिछले चेक की वजह से newValue और oldValue ऐसे कॉर्नर वैल्यू नहीं हो सकते हैं। दोनों के मान एक ही प्रकार के हैं क्योंकि एक ही फ़ील्ड से संबंधित है। धन्यवाद।
तहसीन तुर्कोज़

3

नई घाटी की स्थिति को मान्य करें:

$scope.$watch('fieldcontainer',function(newVal) {
      if(angular.isDefined(newVal)){
          //Do something
      }
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.