Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Component Constructor Called Twice

I am new to Angular and am running into an issue with the constructor on a child component being called twice, and the second time it is called it is clearing the properties set the first time.

This is the parent component:

@Component({
    selector: 'parent-item',
    templateUrl: '...',
    providers: [ItemService]
})
export class ParentItemComponent {
    public parentItemId;
    public model: ParentItem;

    constructor(itemService: ItemService, elm: ElementRef) {
        this.parentItemId = elm.nativeElement.getAttribute('parentItemId'); 
        itemService.getParentItem(this.parentItemId).subscribe(data => this.model = data);
    }
}

And in the template the child component is referenced:

<child-items [parentItemId]="parentItemId">Loading...</<child-items>

This is the child component:

@Component({
    selector: 'child-items',
    templateUrl: '...',
    providers: [ItemService]
})
export class ChildItemsComponent {
    @Input() public parentItemId: number;
    public items: Observable<ChildItem[]>;

    constructor(private itemService: ItemService) {
        console.log("constructor");
    }

    ngOnInit() {
        if (this.parentItemId) {
            this.items = this.itemService.getChildItems(this.parentItemId);
        }  
        else {
            console.log("Parent Id not set!");
        }
    }
}

And finally the child component template:

<tr *ngFor="let item of items | async">
    <td>...</td>
</tr>

The child components constructor is being called twice, and the second time it is called the parentItemId is set to null and the items property is cleared. If I hardcode the parentId instead of using the input the data is being properly received and displayed in the template, but using the input value the template shows no results.

I have created a plunker which shows the same behavior here: http://embed.plnkr.co/xaJtfNgbWCUPap2RCJUA/

like image 235
rwdial Avatar asked Nov 18 '16 17:11

rwdial


People also ask

How many times constructor is called in angular?

It is invoked only once when the directive is instantiated. Mostly we use ngOnInit for all the initialization/declaration and avoid stuff to work in the constructor. The constructor should only be used to initialize class members but shouldn't do actual "work".

Why is ngOnInit getting called twice?

Why it is called twice. 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.

How many times will ngOnInit () be called in a component?

ngOnInit()link A callback method that is invoked immediately after the default change detector has checked the directive's data-bound properties for the first time, and before any of the view or content children have been checked. It is invoked only once when the directive is instantiated.

Which one is called first ngOnInit or constructor?

The constructor is called before ngOnInit , at this point the component hasn't been created yet, only the component class has being instantiated thus your dependencies are brought in, but your initialization code will not run.


2 Answers

child-items is not closed properly. Probably because of this error

This

<child-items [parentItemId]="parentItemId">Loading...</<child-items>

should be:

<child-items [parentItemId]="parentItemId">Loading...</child-items>
like image 149
xameeramir Avatar answered Sep 17 '22 12:09

xameeramir


Your problem is that in the app.module you bootstrap both parent and child component:

bootstrap:    [ ParentItemComponent, ChildItemsComponent ]

It has to be

  bootstrap:    [ ParentItemComponent]
like image 34
Yakov Fain Avatar answered Sep 21 '22 12:09

Yakov Fain