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/
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 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.
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.
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.
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>
Your problem is that in the app.module you bootstrap both parent and child component:
bootstrap: [ ParentItemComponent, ChildItemsComponent ]
It has to be
bootstrap: [ ParentItemComponent]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With