meaning - angularjs tutorial pdf




Angular2 परिवर्तन का पता लगाने: ngOnChanges नेस्टेड ऑब्जेक्ट के लिए फायरिंग नहीं (9)

मुझे पता है कि मैं इस बारे में पूछने वाला पहला व्यक्ति नहीं हूं, लेकिन मुझे पिछले सवालों का जवाब नहीं मिला। मेरे पास यह एक घटक में है

<div class="col-sm-5">
    <laps
        [lapsData]="rawLapsData"
        [selectedTps]="selectedTps"
        (lapsHandler)="lapsHandler($event)">
    </laps>
</div>

<map
    [lapsData]="rawLapsData"
    class="col-sm-7">
</map>

कंट्रोलर में rawLapsdata को समय-समय पर rawLapsdata जाता है।

laps , डेटा एक सारणीबद्ध प्रारूप में HTML के रूप में आउटपुट है। जब भी rawLapsdata बदलता है तो यह बदल जाता है।

मेरे map घटक को Google मानचित्र पर मार्करों को फिर से ngOnChanges करने के लिए ngOnChanges को ट्रिगर के रूप में उपयोग करने की आवश्यकता है। समस्या यह है कि ngOnChanges तब फायर नहीं करता है जब rawLapsData माता-पिता में बदल जाती है। मैं क्या कर सकता हूँ?

import {Component, Input, OnInit, OnChanges, SimpleChange} from 'angular2/core';

@Component({
    selector: 'map',
    templateUrl: './components/edMap/edMap.html',
    styleUrls: ['./components/edMap/edMap.css']
})
export class MapCmp implements OnInit, OnChanges {
    @Input() lapsData: any;
    map: google.maps.Map;

    ngOnInit() {
        ...
    }

    ngOnChanges(changes: { [propName: string]: SimpleChange }) {
        console.log('ngOnChanges = ', changes['lapsData']);
        if (this.map) this.drawMarkers();
    }

अपडेट: ngOnChanges काम नहीं कर रहा है, लेकिन ऐसा लगता है कि जैसे लैप्सडाटा अपडेट किया जा रहा है। NgInit में ज़ूम परिवर्तन के लिए एक ईवेंट श्रोता है जो इसे कॉल भी करता है। जब मैं ज़ूम बदलता हूं तो मुझे वास्तव में मार्करों में बदलाव दिखाई देता है। तो केवल मुद्दा यह है कि इनपुट डेटा में बदलाव के समय मुझे सूचना नहीं मिलती है।

माता-पिता में, मेरे पास यह रेखा है। (याद रखें कि परिवर्तन लैप्स में परिलक्षित होता है, लेकिन मानचित्र में नहीं)।

this.rawLapsData = deletePoints(this.rawLapsData, this.selectedTps);

और ध्यान दें कि this.rawLapsData अपने आप में एक बड़े जेन्स ऑब्जेक्ट के बीच में एक पॉइंटर है

this.rawLapsData = this.main.data.TrainingCenterDatabase.Activities[0].Activity[0].Lap;

आपकी समस्या के समाधान के लिए मेरे पास 2 उपाय हैं

  1. object डेटा परिवर्तित या नहीं का पता लगाने के लिए ngDoCheck का उपयोग करें
  2. मूल घटक से object = Object.create(object) द्वारा एक नए स्मृति पते पर object असाइन करें।

एरे के मामले में आप इसे इस तरह से कर सकते हैं:

.ts फ़ाइल (पेरेंट घटक) जहाँ आप अपने rawLapsData को अपडेट कर रहे हैं, इसे इस तरह से करें:

rawLapsData = somevalue; // change detection will not happen

उपाय:

rawLapsData = {...somevalue}; //change detection will happen

और ngOnChanges को चाइल्ड कंपोनेंट में बुलाया जाएगा


ठीक है तो इसके लिए मेरा समाधान था:

this.arrayWeNeed.DoWhatWeNeedWithThisArray();
const tempArray = [...arrayWeNeed];
this.arrayWeNeed = [];
this.arrayWeNeed = tempArray;

और यह मुझे ngOnChanges ट्रिगर करता है


मार्क राजकोक के दूसरे समाधान के विस्तार के रूप में

जब भी आप सरणी सामग्री में कोई परिवर्तन करते हैं, तो एक नया सरणी निर्दिष्ट करें। फिर ngOnChanges () कहा जाएगा क्योंकि सरणी (संदर्भ) एक परिवर्तन के रूप में दिखाई देगा

आप इस तरह से सरणी की सामग्री को क्लोन कर सकते हैं:

rawLapsData = rawLapsData.slice(0);

इसका जिक्र मैं इसलिए कर रहा हूं

rawLapsData = Object.assign ({}, rawLapsData);

मेरे लिए काम नहीं किया। आशा है कि ये आपकी मदद करेगा।


मैं उसी जरूरत पर ठोकर खाई। और मैंने इस पर बहुत कुछ पढ़ा है, यहाँ इस विषय पर मेरा तांबा है।

यदि आप पुश पर अपनी परिवर्तन पहचान चाहते हैं, तो आपके पास यह तब होगा जब आप किसी वस्तु के मूल्य को दाईं ओर बदलते हैं? और आपके पास यह भी होगा यदि आप किसी तरह वस्तुओं को हटाते हैं।

जैसा कि पहले ही कहा गया है, changeDetectionStrategy.onPush का उपयोग करें

कहते हैं कि आपके पास यह घटक है, जिसमें बदलाव के साथ बदलाव करें।

<component [collection]="myCollection"></component>

तब आप एक आइटम को धक्का देंगे और परिवर्तन का पता लगाने को ट्रिगर करेंगे:

myCollection.push(anItem);
refresh();

या आप किसी आइटम को निकालेंगे और परिवर्तन का पता लगाने के लिए ट्रिगर करेंगे:

myCollection.splice(0,1);
refresh();

या आप एक आइटम के लिए एक attrbibute मान को बदल देंगे और परिवर्तन का पता लगाने को ट्रिगर करेंगे:

myCollection[5].attribute = 'new value';
refresh();

ताज़ा करने की सामग्री:

refresh() : void {
    this.myCollection = this.myCollection.slice();
}

स्लाइस विधि ठीक उसी एरे को लौटाती है, और [=] साइन इसके लिए एक नया संदर्भ बनाते हैं, जिससे आपको हर बार जरूरत पड़ने पर परिवर्तन का पता चलता है। आसान और पठनीय :)

सादर,


मैंने यहां बताए गए सभी समाधानों की कोशिश की है, लेकिन किसी कारण के लिए ngOnChanges() अभी भी मेरे लिए आग नहीं ngOnChanges() है। तो मैंने इसे इस के साथ बुलाया this.ngOnChanges() उस सेवा को कॉल करने के बाद जो मेरे सरणियों को फिर से this.ngOnChanges() और यह काम किया .... सही है? शायद ऩही। साफ? बिलकुल नहीं। काम करता है? हाँ!


यहाँ एक हैक है कि बस मुझे इस एक के साथ मुसीबत से बाहर मिला है।

तो ओपी के लिए एक समान परिदृश्य - मुझे एक नेस्टेड कोणीय घटक मिला है, जिसे डेटा को इसके नीचे पारित करने की आवश्यकता है, लेकिन इनपुट एक सरणी की ओर इशारा करता है, और जैसा कि ऊपर उल्लेख किया गया है, कोणीय परिवर्तन नहीं देखता है क्योंकि यह जांच नहीं करता है सरणी की सामग्री।

तो इसे ठीक करने के लिए मैं एक परिवर्तन का पता लगाने के लिए एंगुलर के लिए एक स्ट्रिंग में सरणी को परिवर्तित करता हूं, और फिर नेस्टेड घटक I में विभाजित करता हूं (',') स्ट्रिंग को फिर से एक सरणी में और इसके सुखद दिनों को फिर से।


सबसे साफ दृष्टिकोण नहीं है, लेकिन आप हर बार जब आप मूल्य बदल सकते हैं, तो आप ऑब्जेक्ट को क्लोन कर सकते हैं?

   rawLapsData = Object.assign({}, rawLapsData);

मुझे लगता है कि मैं अपने स्वयं के ngDoCheck() को लागू करने पर इस दृष्टिकोण को पसंद करूंगा लेकिन शायद @ GünterZöchbauer जैसा कोई व्यक्ति इसमें झंकार कर सकता है।


rawLapsData उसी सरणी को इंगित rawLapsData रहता है, भले ही आप सरणी की सामग्री को संशोधित करें (जैसे, आइटम जोड़ें, आइटम निकालें, आइटम बदलें)।

परिवर्तन का पता लगाने के दौरान, जब कोणीय परिवर्तन के लिए घटकों के इनपुट गुणों की जाँच करता है, तो यह गंदे जाँच के लिए (अनिवार्य रूप से) === का उपयोग करता है। सरणियों के लिए, इसका मतलब है कि सरणी संदर्भ (केवल) गंदे चेक किए गए हैं। चूँकि rawLapsData सरणी संदर्भ नहीं बदल रहा है, ngOnChanges() नहीं कहा जाएगा।

मैं दो संभावित समाधानों के बारे में सोच सकता हूं:

  1. ngDoCheck() लागू करें और यह निर्धारित करने के लिए अपने स्वयं के परिवर्तन का पता लगाने का तर्क दें कि क्या सरणी सामग्री बदल गई है। (जीवनचक्र के हुक डॉक्स का एक उदाहरण है ।)

  2. जब भी आप सरणी सामग्री में कोई परिवर्तन करते हैं, तो एक नया सरणी निर्दिष्ट करें। फिर ngOnChanges() कहा जाएगा क्योंकि सरणी (संदर्भ) एक परिवर्तन के रूप में दिखाई देगा।

आपके जवाब में, आप एक और समाधान के साथ आए।

यहाँ ओपी पर कुछ टिप्पणियों को दोहराते हुए:

मैं अभी भी यह नहीं देखता कि कैसे बदलाव पर उठा सकते हैं (निश्चित रूप से यह ngOnChanges() खुद के बराबर कुछ का उपयोग करना चाहिए?) जबकि map नहीं कर सकता।

  • laps घटक में आपका कोड / टेम्प्लेट lapsData सरणी में प्रत्येक प्रविष्टि पर लूप करता है, और सामग्री को प्रदर्शित करता है, इसलिए डेटा के प्रत्येक टुकड़े पर कोणीय बाइंडिंग प्रदर्शित होते हैं।
  • यहां तक ​​कि जब एंगुलर घटक के इनपुट गुणों ( === चेकिंग का उपयोग करके) में किसी भी बदलाव का पता नहीं लगाता है, तब भी यह (डिफ़ॉल्ट रूप से) सभी टेम्पलेट बाइंडिंग की गंदे जांच करता है। जब उनमें से कोई भी परिवर्तन होता है, तो कोणीय DOM को अपडेट करेगा। वही तुम देख रहे हो।
  • maps घटक की संभावना है कि इसकी lapsData इनपुट प्रॉपर्टी में इसके टेम्पलेट में कोई बाइंडिंग नहीं है, है ना? वह अंतर स्पष्ट करेगा।

ध्यान दें कि दोनों घटक में rawLapsData और मूल घटक में rawLapsData सभी एक ही / एक सरणी के लिए इंगित करते हैं। इसलिए, भले ही lapsData किसी भी (संदर्भ) बदलाव को lapsData इनपुट गुणों पर ध्यान नहीं देता है, घटक "मिलता है" / किसी भी सरणी सामग्री को देखते हैं क्योंकि वे सभी साझा / संदर्भ करते हैं कि एक सरणी। हमें इन परिवर्तनों को प्रचारित करने के लिए कोणीय की आवश्यकता नहीं है, जैसे हम एक आदिम प्रकार (स्ट्रिंग, संख्या, बूलियन) के साथ करेंगे। लेकिन एक आदिम प्रकार के साथ, मूल्य में कोई भी परिवर्तन हमेशा ngOnChanges() ट्रिगर ngOnChanges() - जो कि आपके उत्तर / समाधान में आपके द्वारा शोषण किया गया कुछ है।

जैसा कि आप शायद अब तक पता लगा चुके हैं कि इनपुट इनपुट गुणों में सरणी इनपुट गुणों के समान व्यवहार होता है।





angular