Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ngOnInit should never be called twice, even if an error happens #6782

Closed
tbosch opened this issue Jan 30, 2016 · 32 comments
Closed

ngOnInit should never be called twice, even if an error happens #6782

tbosch opened this issue Jan 30, 2016 · 32 comments
Labels
area: core Issues related to the framework runtime effort1: hours type: bug/fix

Comments

@tbosch
Copy link
Contributor

tbosch commented Jan 30, 2016

Right now, if an error happens during detecting changes of content/view children of a component, ngOnInit will be called twice (seen in DynamicChangeDetector).
This can lead to follow up errors that hide the original error.

/cc @matanlurey

@dylanbaxter
Copy link

+1!

@dalamgir
Copy link

If no one has this yet i can take this on.

@innoproject
Copy link

I get the same issue. I tried to pass in the object from one component to another using @input decorator, and using the parameter i build another object in the passed component in ngOninit lifecycle method. In the first iteration i was able to get the value but in the second iteration (which shouldn't happen) reinitialized the values back to null.

@tbosch
Copy link
Contributor Author

tbosch commented Sep 2, 2016

@innoproject Could you create a plunker?

@mhevery mhevery added area: core Issues related to the framework runtime and removed comp: core/change_detection labels Sep 7, 2016
@ihrimech
Copy link

ihrimech commented Sep 27, 2016

I'm trying to use leaflet library an add a map to a component. It seems like the ngOnInit is called twice which is causing an issue to the map instantiation. Is there any workaround to this issue ?

@vicb
Copy link
Contributor

vicb commented Sep 27, 2016

@ihrimech Try to reproduce in a Plunker. Thanks (& include version info in your comments)

@ihrimech
Copy link

Can't reproduce it anymore. I've put it in a try-catch block meanwhile so I could go forward with the app development and now It seems to be working fine without. I'll keep it like this and make a plunker when the problem gets back.
Angular version 2.0.0

@vicb vicb closed this as completed Sep 28, 2016
@DILEEPKUMAREBIX
Copy link

DILEEPKUMAREBIX commented Oct 6, 2016

Hi,
I am also facing this problem. ngOninit() calling twice of my component so @input property assigned with null.
First time i am getting actual value, but 2nd time in ngOninit() @input property assigned with null.

Please look into this. I just want to skip second time call.

I cant create plunkr but i shared my Component code below.
I used two times the same component and below is my console log:
"
AppComponent true
DateTimePicker.ts:64 AppComponent true
core.umd.js:241 Angular 2 is running in the development mode. Call enableProdMode() to enable the production mode.
DateTimePicker.ts:64 AppComponent undefined
core.umd.js:241 Angular 2 is running in the development mode. Call enableProdMode() to enable the production mode.
"

`import {Component,OnInit,Input,ElementRef} from '@angular/core';
import {DateTime} from './datetime';

@component({
selector: 'DateTimePicker',
providers: [DateTime],
directives: [],
templateUrl: './app/dateTime.tpl.html',
styleUrls: ['app/dateTime.component.css']
})

export class DateTimePickerComponent implements OnInit{

@input() public dateAndTime:Boolean;

/**

  • public variables
    */
    public selectedDate: Date; //currently selected date
    public hour: number;
    public minute: number;

    public el: HTMLElement; // this component element
    public monthData: any; // month calendar data

    public formattedStrDate: any;
    public dateFormat: any;
    public showPicker: any;
    public compTop: any;
    public compLeft: any;

    public get year ():number {
    return this.selectedDate.getFullYear();
    };

    public get month ():number {
    return this.selectedDate.getMonth();
    };

    public get day ():number {
    return this.selectedDate.getDate();
    };

    public get today ():Date {
    let dt = new Date();
    dt.setHours(0);
    dt.setMinutes(0);
    dt.setSeconds(0);
    dt.setMilliseconds(0);
    return dt;
    };

    constructor(elementRef:ElementRef,public dateTime: DateTime) {
    try {
    this.el = elementRef.nativeElement;
    } catch (error) {
    console.log(error);
    }
    };

    ngOnInit() {
    try {
    console.log("AppComponent "+this.dateAndTime);
    this.formattedStrDate = "2016/10/11 10:44 PM";
    this.dateFormat = "YYYY/MM/DD hh:mm A";
    this.showPicker = false;
    this.initDateTime(new Date());
    var item:any = this.el.querySelector("#dateTextId");
    this.compTop = item.offsetTop + 35;
    this.compLeft = item.offsetLeft + 10;
    } catch (error) {
    console.log(error);
    }

    };

    pickerClickHandler() {
    this.showPicker = true;
    this.getDateFromText();
    var item:any = this.el.querySelector("#datetimePickerId");
    item.style.top = this.compTop;
    item.style.left = this.compLeft;
    };

    getDateFromText() {
    this.selectedDate = this.dateTime.momentParse(this.formattedStrDate,this.dateFormat);
    this.monthData = this.dateTime.getMonthData(this.selectedDate.getFullYear(), this.selectedDate.getMonth());
    };

    public toDate (year:number, month:number, day:number):Date {
    return new Date(year, month, day);
    };

    public toDateOnly (date:Date) {
    return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0);
    };

    updateMonthData(num: number) {
    this.monthData = this.dateTime.getMonthData(this.monthData.year, this.monthData.month + num);
    };

    updateYear(){
    var yearSelector:any = this.el.querySelector("#yearSelector");
    this.monthData = this.dateTime.getMonthData(parseInt(yearSelector.value) , this.monthData.month);
    };

    public selectToday(){
    var date = new Date();
    this.selectedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
    this.monthData = this.dateTime.getMonthData(date.getFullYear(), date.getMonth());
    this.selectDate();
    };

    public selectDate (dayNum?:number) {
    if (dayNum) {
    this.selectedDate = new Date(this.monthData.year, this.monthData.month, dayNum);
    }
    if (this.dateAndTime){
    var hoursStepper:any = this.el.querySelector("#hoursRange");
    this.hour = parseInt(hoursStepper.value);
    var minutesStepper:any = this.el.querySelector("#minutesRange");
    this.minute = parseInt(minutesStepper.value);
    }
    this.selectedDate.setHours(parseInt( ''+this.hour || '0', 10));
    this.selectedDate.setMinutes(parseInt( ''+this.minute|| '0', 10));
    this.formattedStrDate = this.dateTime.momentFormatDate(this.selectedDate,this.dateFormat);
    this.showPicker = false;
    };

    public initDateTime (date:Date) {
    date = date || new Date();
    this.selectedDate = date;
    this.hour = this.selectedDate.getHours();
    this.minute = this.selectedDate.getMinutes();
    this.monthData = this.dateTime.getMonthData(this.year, this.month);
    };
    }`

@DILEEPKUMAREBIX
Copy link

@tbosch so what is work around for this issue to skip second time call?
Thanks in advance.

@prabhatsharma
Copy link

Still reproducible with 2.0.2

@sioquim
Copy link

sioquim commented Oct 7, 2016

I get the same issue. I tried to pass in the object from one component to
another using @input decorator, and using the parameter i build another
object in the passed component in ngOninit lifecycle method. In the first
iteration i was able to get the value but in the second iteration (which
shouldn't happen) reinitialized the values back to null.

You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
#6782 (comment)

@tbosch
Copy link
Contributor Author

tbosch commented Oct 10, 2016

@francosioquim @prabhatsharma @DILEEPKUMAREBIX We really need a plunker that shows it. Otherwise it is super hard to reproduce your problem...

@agalazis
Copy link

@francosioquim for me inputs were undefined not null (on the retriggered onInit)

@amardeep157
Copy link

Hi,

Well the Problem in my case was the way I was bootstrapping the Child Components.
In my @NgModule decorator’s metadata object ,I was passing ‘child component’ in the bootstap property along with ‘parent component’.
Passing the child components in bootstap property was resetting my child components properties and making OnInit() fired twice.

@NgModule({
imports: [ BrowserModule,FormsModule ], // to use two-way data binding ‘FormsModule’
declarations: [ parentComponent,Child1,Child2], //all components
//bootstrap: [parentComponent,Child1,Child2] // will lead to errors in binding Inputs in Child components
bootstrap: [parentComponent] //use parent components only
})

@Abuleilei
Copy link

Thanks @amardeep157 ! Solved my problem.

@p0rsche
Copy link

p0rsche commented Apr 11, 2017

Still reproducible in 4.0.0, but due the nature of our project (relatively big) it's very hard to find where the error happens.

@prabhatsharma
Copy link

prabhatsharma commented Apr 11, 2017 via email

@p0rsche
Copy link

p0rsche commented Apr 11, 2017

The problem is that we cannot grab the original error. If someone could give a good advice how to catch the original error it would be great.

@razvanmitre
Copy link

We are also experiencing the problem. It is like routerLinkActive reinitializes the component.

@tbosch
Copy link
Contributor Author

tbosch commented Apr 26, 2017

This still happens in production mode, tracking here: #15925

@jjlorenzo
Copy link

@razvanmitre I face the same issue with routerLinkActive, for know I remove this because I don't have time to properly debug the problem

@jamilalisgandarov
Copy link

I have deleted routerLinkActive, but still happens

@RajendrasinhParmar
Copy link

Any updates on this issue?
I'm also having the same issue in my project.

@onemantooo
Copy link

onemantooo commented Jan 22, 2019

still have same trouble.
Constructor fires once? oninit twice

@eivindvea
Copy link

Same trouble here

@ravindra-clairvoyant
Copy link

I am also facing the same issue, the constructor is getting called twice. I have created a thread here. does anyone have any workaround for this?

@adornala
Copy link

I was facing the same issue a while ago. Looks like, Angular 'nativeNode' is not destroyed properly, I was using the same selector name for creating customElements and component selector. During app startup 'ERROR TypeError: Cannot read property 'nativeNode' of null' shows up in the console, from what I understand angular tries 2nd time if it fails the 1st time, when angular tries the 2nd time it looks like it resolves the error.

Try differentiating selector names between @component({selector: ''}) and createCustomElement(). If you are creating custom elements, it should help. That's the fix I had for now, at least it worked for me.

@aashkashah
Copy link

2019 and still same issue. Constructor and NgOnInit called twice

@dalvarezsmiet
Copy link

Yep, still happens, ngOnInit and constructor fired twice just a per website is starting. Very disappointing, as it seems not possible to avoid it

@DILEEPKUMAREBIX
Copy link

DILEEPKUMAREBIX commented Sep 17, 2019 via email

@dalvarezsmiet
Copy link

No way, production mode is already enabled in my project, and the ngOnInit is being fired twice, always. I've read about some binding errors or HTML non-closed tags that may cause this behavior, but I've checked it, and it's not the case... It's really weird

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Oct 19, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: core Issues related to the framework runtime effort1: hours type: bug/fix
Projects
None yet
Development

No branches or pull requests