core.js:6406 ERROR TypeError: Cannot read property 'id' of undefined
Solution 1
Can you try paramsInheritanceStrategy
?
@NgModule({
imports: [RouterModule.forRoot(routes,{
paramsInheritanceStrategy: 'always'
})],
exports: [RouterModule]
})
export class AppRoutingModule { }
You need to capture the parent route params as well
Solution 2
Below code is working for me:
In tsconfig.json of you Angular project
{
...
"angularCompilerOptions": {
"enableIvy": false
}
}
Solution 3
Try to use the elvis operator ? . lets say you want to access object.id try object?.id. Usually it happens when you try to access data that maybe be nullable or its reference maybe missing
Admin
Updated on August 21, 2022Comments
-
Admin over 1 year
I have an angular 8 application. And a create function. But I can't create a item, because of the id is null.
Of course I googled for this. But I think this is a specific case.
So this is the the template where the function will be triggered:
<button *ngIf="isNew" mat-raised-button color="primary" [appSubmitIfValid]="editItemForm" (valid)="save()" i18n>Create</button>
and this is the actual function:
this.dossierService.newDossierItem(this.dossier.id, dossierItemDto) .subscribe(item => { this.item = item; this.dossierItems.unshift(item); this.sortDossierItems(); this.isNew = false; form.enable(); form.markAsPristine(); this.errorProcessor.openSuccessSnackBar($localize`Item is saved`); }, error => this.handleError(error));
and this is my router.ts:
{ path: ':dossierId', component: ViewComponent, children: [ { path: 'item/new/:dossierItemType', component: ItemComponent} ], resolve: { dossier: DossierResolver, dossierItems: DossierItemsResolver } },
So I get an error on this line:
this.dossierService.newDossierItem(this.dossier.id, dossierItemDto)
that
id
isnull
.But what I have to change?
Thank you
Update:
This is the link for adding a new item: view.component.html:
<ng-template mat-tab-label #interviews> <mat-icon class="interviews">speaker_notes</mat-icon> <span i18n>Interview reports</span>{{ dossierItemsCountString(itemTypes.Interview) }} <a [routerLink]="['../' , dossier.id , 'item' , 'new', itemTypes.Interview]"> <mat-icon class="add_box">add</mat-icon> </a> </ng-template>
The problem is with routing. Because if I do this:
{ path: ':dossierId/item/new/:dossierItemType', component: ItemComponent, resolve: { dossier: DossierResolver, dossierItems: DossierItemsResolver } },
then I can create a new item. But this is not what I want because the new item will be then loaded in a new view.
So that is why I have this:
{ path: ':dossierId', component: ViewComponent, children: [ { path: 'item/new/:dossierItemType', component: ItemComponent} ], resolve: { dossier: DossierResolver, dossierItems: DossierItemsResolver } },
But then dossier is every time null.
this is full item.component.ts code:
export class ItemComponent implements OnInit { itemTypes = DossierItemTypeDto; formBuilder = new FormBuilder(); isNew = false; editItemForm: FormGroup; dossierItemId: string; item: DossierItemDto; dossierItems: DossierItemDto[]; dossier: DossierDto; globalErrors: ValidationErrors; constructor(private dossierService: DossierService, private route: ActivatedRoute, private router: Router, private errorProcessor: ErrorProcessor) { this.dossier = this.route.snapshot.data.dossier; this.dossierItemId = this.route.snapshot.params.dossierItemId; this.isNew = this.dossierItemId === undefined; this.dossierItems = this.route.snapshot.data.dossierItems; if (this.isNew) { this.item = { title: '', itemType: this.route.snapshot.params.dossierItemType, date: moment().format('Y-MM-DD'), createdAt: moment().format('Y-MM-DD'), body: '' }; } else { this.item = this.dossierItems.find(i => i.id === this.dossierItemId); } } ngOnInit(): void { this.editItemForm = this.formBuilder.group({ title: this.formBuilder.control(this.item.title, [Validators.required]), itemType: this.formBuilder.control(this.item.itemType, [Validators.required]), date: this.formBuilder.control(moment(this.item.date, 'Y-MM-DD'), [Validators.required]), body: this.formBuilder.control(this.item.body, [Validators.required, Validators.maxLength(2097152)]) }); } save(): void { const form = this.editItemForm; const dossierItemDto: DossierItemPostDto = { title: form.controls.title.value, itemType: form.controls.itemType.value, date: (form.controls.date.value as moment.Moment).format('Y-MM-DD'), body: form.controls.body.value }; form.disable(); if (!this.isNew) { this.dossierService.updateDossierItemById(this.dossier.id, this.item.id, dossierItemDto) .subscribe(item => { this.item = item; this.sortDossierItems(); form.enable(); form.markAsPristine(); this.errorProcessor.openSuccessSnackBar($localize`Item is saved`); }, error => this.handleError(error)); } else { this.dossierService.newDossierItem(this.dossier.id, dossierItemDto) .subscribe(item => { this.item = item; this.dossierItems.unshift(item); this.sortDossierItems(); this.isNew = false; form.enable(); form.markAsPristine(); this.errorProcessor.openSuccessSnackBar($localize`Item is saved`); }, error => this.handleError(error)); } } }
But if I try this:
{ path: ':dossierId', component: ViewComponent, children: [ { path: 'item/new/:dossierItemType', component: ItemComponent} ], resolve: { dossier: DossierResolver, dossierItems: DossierItemsResolver } },
oke, this is weird, Because on this:
ngOnInit(): void { this.route.params.subscribe((params: Params) => { this.dossier.id = params.dossierId; });
in the debugger. I see the first time that the id is set:
"06637e72-8915-4735-9400-4ef7705194ea"
but if I do a f8 then the id is null:
this.dossier.id = params.dossierId;
and the route I have like this:
{ path: ':dossierId', component: ViewComponent, children: [ { path: 'item/new/:dossierItemType', component: ItemComponent} ], resolve: { dossier: DossierResolver, dossierItems: DossierItemsResolver } },
So this is called two times:
this.route.params.subscribe((params: Params) => { this.dossier.id = params.dossierId; });
Dont understand why