'Getting error TS2531: Object is possibly 'null' using <mat-error>

I'm using a FormArray of FormGroups that either has values from the database or default values.

Form Validation works based on the FormGroup selected, but I can't reference and display the corresponding error message for the field. I keep getting this error message:

enter image description here

I tried adding ? and !, but TypeScript still won't compile.

Why can I reference the field value and validation, but not the error object for the field?

Any help would be greatly appreciated.

Thanks!

HTML

   <form *ngIf="collectionImageForm" [formGroup]="collectionImageForm" #formDirective="ngForm">
      <div formArrayName="collectionImageArray">
         <div *ngFor="let image of collectionImageArray.controls; let i = index" [formGroupName]="i">
            <div fxLayout="row" fxLayout.xs="column" fxLayoutAlign.gt-xs="start center" fxLayoutGap.gt-xs="30px">
               <div fxFlex="auto">
                  <mat-form-field class="full-width" floatLabel="always" appearance="outline">
                     <mat-label>Type Name</mat-label>
                     <input id="typeName" name="typeName" formControlName="typeName" matInput type="text" value="{{image.value.typeName}}" readonly (keyup)="validateFormCompletion()">
                  </mat-form-field>
               </div>
               <div fxFlex="auto">
                  <mat-form-field class="full-width" floatLabel="always" appearance="outline">
                     <mat-label>File Name</mat-label>
                     <input id="fileName" name="fileName" formControlName="fileName" matInput type="text" value="{{image.value.fileName}}" (keyup)="validateFormCompletion()">
                  </mat-form-field>
               </div>
               <div fxFlex="auto">
                  <mat-form-field class="full-width" floatLabel="always" appearance="outline">
                     <mat-label>Width</mat-label>
                     <input id="width" name="width" formControlName="width" matInput type="text" value="{{image.value.width}}" (keyup)="validateFormCompletion()">
                  </mat-form-field>
               </div>
               <div fxFlex="auto">
                  <mat-form-field class="full-width" floatLabel="always" appearance="outline">
                     <mat-label>Height</mat-label>
                     <input id="height" name="height" formControlName="height" matInput type="text" value="{{image.value.height}}" (keyup)="validateFormCompletion()">
                     <mat-error *ngIf="image.get('height').errors!.required">Image Height is required</mat-error>
                  </mat-form-field>
               </div>
               <div fxFlex="auto">
                  <mat-slide-toggle formControlName="display">Display</mat-slide-toggle>
               </div>
               <div *ngIf="( ( this.haveCard ) || ( this.havePodcast ) || ( this.havePoster ) )" fxFlex="auto">
                  <button type="submit" mat-raised-button color="primary" (click)="update( i, formDirective )" [disabled]="collectionImageFormInvalid">Update</button>
               </div>
               <div *ngIf="( ( this.haveCard == false ) || ( this.havePodcast == false ) || ( this.havePoster == false ) )" fxFlex="auto">
                  <button type="submit" mat-raised-button color="primary" (click)="save( i, formDirective )" >Save</button>
               </div>
            </div>
         </div>
      </div>
   </form>

TYPESCRIPT

   getCollectionImages()
   {
      this.haveCard = false;
      this.havePodcast = false;
      this.havePoster = false;

      // Get Collection Images
      this.collectionImageService.load( this.languageParameter, this.collectionParameter ).subscribe
      ( images =>
         {
            this.images = images;
            this.collectionImageArray.clear();

            for ( let i = 0; i < this.images.length; i++ )
            {
               if ( this.images[i].typeID == 1 )
               {
                  this.haveCard = true;
               }
               else if ( this.images[i].typeID == 2 )
               {
                  this.havePodcast = true;
               }
               else if ( this.images[i].typeID == 3 )
               {
                  this.havePoster = true;
               }

               this.imageFormGroup = this.formBuilder.group
               (
                  {
                     collectionID: this.images[i].collectionID,
                     languageID: this.images[i].languageID,
                     typeID: this.images[i].typeID,
                     typeName: this.images[i].typeName,
                     fileName: [ this.images[i].fileName, [Validators.required, Validators.pattern( "^[a-zA-Z0-9'\"&. -]+$" )] ],
                     width: [ this.images[i].width, [Validators.required, Validators.pattern( "^[0-9]+$" )] ],
                     height: [ this.images[i].height, [Validators.required, Validators.pattern( "^[0-9]+$" )] ],
                     display: this.images[i].display
                  }
               )

               this.collectionImageArray.push( this.imageFormGroup )
            }

            if ( this.haveCard == false )
            {
               this.imageFormGroup = this.formBuilder.group
               (
                  {
                     collectionID: this.collectionParameter,
                     languageID: this.languageParameter,
                     typeID: 1,
                     typeName: "Card",
                     fileName: [ ".jpg", [Validators.required, Validators.pattern( "^[a-zA-Z0-9'\"&. -]+$" )] ],
                     width: [ 480, [Validators.required, Validators.pattern( "^[0-9]+$" )] ],
                     height: [ 270, [Validators.required, Validators.pattern( "^[0-9]+$" )] ],
                     display: true
                  }
               )

               this.collectionImageArray.push( this.imageFormGroup )
            }

            if ( this.havePodcast == false )
            {
               this.imageFormGroup = this.formBuilder.group
               (
                  {
                     collectionID: this.collectionParameter,
                     languageID: this.languageParameter,
                     typeID: 2,
                     typeName: "Podcast",
                     fileName: [ ".jpg", [Validators.required, Validators.pattern( "^[a-zA-Z0-9'\"&. -]+$" )] ],
                     width: [ 1400, [Validators.required, Validators.pattern( "^[0-9]+$" )] ],
                     height: [ 1400, [Validators.required, Validators.pattern( "^[0-9]+$" )] ],
                     display: true
                  }
               )

               this.collectionImageArray.push( this.imageFormGroup )
            }

            if ( this.havePoster == false )
            {
               this.imageFormGroup = this.formBuilder.group
               (
                  {
                     collectionID: this.collectionParameter,
                     languageID: this.languageParameter,
                     typeID: 3,
                     typeName: "Poster",
                     fileName: [ ".jpg", [Validators.required, Validators.pattern( "^[a-zA-Z0-9'\"&. -]+$" )] ],
                     width: [ 854, [Validators.required, Validators.pattern( "^[0-9]+$" )] ],
                     height: [ 480, [Validators.required, Validators.pattern( "^[0-9]+$" )] ],
                     display: true
                  }
               )

               this.collectionImageArray.push( this.imageFormGroup )
            }

            this.collectionImageService.displayImageArrayInfo( this.collectionImageArray );
         }
      );

      // Validate Form Completion
      //this.validateFormCompletion();
   }

UPDATE

Adding what Yong said compiles TypeScript now, but I now get this error:

core.js:6479 ERROR TypeError: Cannot read properties of null (reading 'required')
    at MediaCollectionImagesComponent_form_9_div_3_Template (media-collection-images.component.html:68)
    at executeTemplate (core.js:9598)
    at refreshView (core.js:9464)
    at refreshEmbeddedViews (core.js:10589)
    at refreshView (core.js:9488)
    at refreshEmbeddedViews (core.js:10589)
    at refreshView (core.js:9488)
    at refreshComponent (core.js:10635)
    at refreshChildComponents (core.js:9261)
    at refreshView (core.js:9514)

I don't understand what could be null. All the fields have values when the screen renders. What am I missing? Thanks

UPDATE 2

<mat-error *ngIf="image.get('height')?.errors?.required">Image Height is required</mat-error>

Changing ! to ? got past this error.



Solution 1:[1]

As far as I can see it's 'image' that might be null so try with image!.get('height').errors.required

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nicola