typescript - जाँच के बाद अभिव्यक्ति___ बदल गई है




angular (9)

आप rxjs Observable.timer फ़ंक्शन का उपयोग करके एक टाइमर भी बना सकते हैं, और फिर अपनी सदस्यता में संदेश को अपडेट कर सकते हैं:

Observable.timer(1).subscribe(()=> this.updateMessage());

इस सरल plunk में घटक क्यों है

@Component({
  selector: 'my-app',
  template: `<div>I'm {{message}} </div>`,
})
export class App {
  message:string = 'loading :(';

  ngAfterViewInit() {
    this.updateMessage();
  }

  updateMessage(){
    this.message = 'all done loading :)'
  }
}

फेंक:

अपवाद: App @ 0: 5 में 'I’m {{मैसेज}} एक्सप्रेशन चेक होने के बाद बदल गया है। पिछला मान: 'मैं लोड कर रहा हूँ :(': वर्तमान मूल्य: 'मैं सब लोड कर रहा हूँ :)' [मैं {{संदेश}} ऐप @ 0: 5] में हूँ

जब सब मैं कर रहा हूँ एक सरल बाध्यकारी अद्यतन कर रहा है जब मेरा दृष्टिकोण शुरू किया जाता है?


आप अपने कॉल को ngOnInt () में अपडेट करने के लिए अपनी कॉल भी लगा सकते हैं - विधि, कम से कम यह मेरे लिए काम करता है

ngOnInit() {
    this.updateMessage();
}

RC1 में यह अपवाद को ट्रिगर नहीं करता है


इसके लिए मैंने उपरोक्त उत्तरों की कोशिश की है कि कई कोणीय के नवीनतम संस्करण में काम नहीं करता है (6 या बाद में)

मैं सामग्री नियंत्रण का उपयोग कर रहा हूं जो पहले किए गए बाध्यकारी के बाद आवश्यक परिवर्तन करता है।

    export class AbcClass implements OnInit, AfterContentChecked{
        constructor(private ref: ChangeDetectorRef) {}
        ngOnInit(){
            // your tasks
        }
        ngAfterViewInit() {
            this.ref.detectChanges();
        }
    }

मेरे उत्तर को जोड़ते हुए, यह कुछ विशेष समस्या को हल करने में मदद करता है।


क्या आप ngOnInit उपयोग नहीं कर सकते क्योंकि आप केवल सदस्य चर message बदल रहे हैं?

यदि आप किसी चाइल्ड कंपोनेंट @ViewChild(ChildComponent) संदर्भ को एक्सेस करना चाहते हैं, तो आपको वास्तव में ngAfterViewInit साथ इसका इंतजार करना ngAfterViewInit

एक गंदा फिक्स updateMessage() साथ अगले इवेंट लूप में updateMessage() को कॉल करना है।

ngAfterViewInit() {
  setTimeout(() => {
    this.updateMessage();
  }, 1);
}

पहले, ध्यान दें कि यह अपवाद केवल तब होगा जब आप अपने ऐप को देव मोड में चला रहे हों (जो कि डिफ़ॉल्ट रूप से बीटा -0 के रूप में हो): यदि आप ऐप को बूटस्ट्रैप करते समय enableProdMode() कहते हैं, तो यह नहीं मिलेगा फेंक दिया ( अद्यतन प्लंक देखें )।

दूसरा, ऐसा न करें क्योंकि यह अपवाद अच्छे कारण के लिए फेंका जा रहा है: संक्षेप में, जब देव मोड में, परिवर्तन का पता लगाने के हर दौर के तुरंत बाद एक दूसरा दौर होता है, जो सत्यापित करता है कि पहले के अंत से कोई बाइंडिंग नहीं बदली है, जैसा कि यह इंगित करेगा कि परिवर्तन का पता लगाने के कारण ही परिवर्तन हो रहे हैं।

आपके प्लंक में, बाइंडिंग {{message}} को आपके कॉल द्वारा setMessage() में बदल दिया जाता है, जो ngAfterViewInit हुक में होता है, जो शुरुआती बदलाव का पता लगाने वाले मोड़ के एक हिस्से के रूप में होता है। हालांकि यह अपने आप में समस्याग्रस्त नहीं है - समस्या यह है कि setMessage() बाइंडिंग को बदल देता है लेकिन परिवर्तन का पता लगाने के एक नए दौर को ट्रिगर नहीं करता है, जिसका अर्थ है कि यह परिवर्तन तब तक पता नहीं चलेगा जब तक कि भविष्य के परिवर्तन का पता लगाने का दौर कहीं और शुरू न हो जाए। ।

टेकअवे: जो कुछ भी बाध्यकारी होता है उसे बदलने पर परिवर्तन का पता लगाने का एक दौर शुरू करना पड़ता है।

उदाहरण के लिए सभी अनुरोधों के जवाब में अपडेट करें कि कैसे करें : @ टायको का समाधान काम करता है, जैसा कि उत्तर में तीन तरीके @MarkRajcok ने बताया है। लेकिन स्पष्ट रूप से, वे सभी मेरे लिए बदसूरत और गलत महसूस करते हैं, जैसे कि हैक की तरह हमें एनजी 1 पर झुकाव करने की आदत है।

यह सुनिश्चित करने के लिए, कभी-कभी ऐसी परिस्थितियाँ होती हैं जहाँ ये हैक उपयुक्त होते हैं, लेकिन यदि आप इनका उपयोग बहुत अधिक सामयिक आधार पर कर रहे हैं, तो यह एक संकेत है कि आप इसकी प्रतिक्रियाशील प्रकृति को पूरी तरह से अपनाने के बजाय रूपरेखा से लड़ रहे हैं।

IMHO, एक और अधिक मुहावरेदार, "एंगुलर 2 तरीका" इसके निकट है: ( plunk ) की तर्ज पर कुछ

@Component({
  selector: 'my-app',
  template: `<div>I'm {{message | async}} </div>`
})
export class App {
  message:Subject<string> = new BehaviorSubject('loading :(');

  ngAfterViewInit() {
    this.message.next('all done loading :)')
  }
}

मैं @Biranchi की पोस्ट पर टिप्पणी नहीं कर सका क्योंकि मेरे पास पर्याप्त प्रतिष्ठा नहीं है, लेकिन इसने मेरे लिए समस्या को ठीक कर दिया।

एक बात ध्यान दें! यदि चेंजिंग एडिटिंग जोड़ रहा है: ChangeDetectionStrategy.OnPush कंपोनेंट पर काम नहीं किया और इसका चाइल्ड कंपोनेंट ( डंब कंपोनेंट) इसे पैरेंट में भी जोड़ने की कोशिश करता है।

इसने बग को ठीक कर दिया, लेकिन मुझे आश्चर्य है कि इसके दुष्प्रभाव क्या हैं।


यह एक त्रुटि है क्योंकि जब ngAfterViewInit () कहा जाता है तो आपका कोड अपडेट हो जाता है। जब ngAfterViewInit जगह लेता है, तो आपका प्रारंभिक मूल्य बदल गया है, अगर आप ngAfterContentInit () में कॉल करते हैं तो यह एक त्रुटि नहीं करेगा।

ngAfterContentInit() {
    this.updateMessage();
}

यह त्रुटि इसलिए आ रही है क्योंकि मौजूदा मान आरंभ होने के तुरंत बाद अपडेट हो रहा है। इसलिए यदि आप DOM में मौजूदा मूल्य प्रदान करने के बाद नए मूल्य को अपडेट करेंगे, तो यह ठीक काम करेगा। इस लेख में उल्लेख किया गया है। Angular Debugging "अभिव्यक्ति की जाँच के बाद बदल गया है"

उदाहरण के लिए आप उपयोग कर सकते हैं

 ngAfterViewInit() { setTimeout(() => { //code for your new value. }); 

}

या

 ngAfterViewInit() { this.paginator.page .pipe( startWith(null), delay(0), tap(() => this.dataSource.loadLessons(...)) ).subscribe(); } 

जैसा कि आप देख सकते हैं कि मैंने सेटटाइम पद्धति में समय का उल्लेख नहीं किया है। जैसा कि यह ब्राउज़र प्रदान किया गया एपीआई है, जावास्क्रिप्ट एपीआई नहीं है, इसलिए यह ब्राउज़र स्टैक में अलग-अलग चलेगा और तब तक इंतजार करेगा जब तक कि स्टैक आइटम समाप्त न हो जाए।

ब्राउज़र एपीआई एनवोकस की अवधारणा को एक यूट्यूब वीडियो (हैक क्या इवेंट लूप है) में फिलिप रॉबर्ट्स द्वारा समझाया गया है।


ngAfterViewChecked() ने मेरे लिए काम किया:

import { Component, ChangeDetectorRef } from '@angular/core'; //import ChangeDetectorRef

constructor(private cdr: ChangeDetectorRef) { }
ngAfterViewChecked(){
   //your code to update the model
   this.cdr.detectChanges();
}




angular