core.js:6406 ERROR TypeError: Cannot read property 'id' of undefined

16,714

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

Share:
16,714
Admin
Author by

Admin

Updated on August 21, 2022

Comments

  • Admin
    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 is null.

    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
        }
      },
    
    

    enter image description here

    enter image description here

    So this is called two times:

     this.route.params.subscribe((params: Params) => {
          this.dossier.id = params.dossierId;
        });
    

    Dont understand why