Home > front end >  Why does TypeScript ask me to initialise a property if I'm getting it's value from local r
Why does TypeScript ask me to initialise a property if I'm getting it's value from local r

Time:04-26

I just started to learn Angular.

This is my custom component's Template

    <div >
  <div >
    <form action="">
      <div >
        <div >
          <label for="name">Name</label>
          <input type="text" id="name"  #nameInput />
        </div>
        <div >
          <label for="amount">Amount</label>
          <input type="number" id="amount"  #amountInput />
        </div>
      </div>
      <div >
        <div >
          <button  type="submit" (click)="onAddItem()">
            Add
          </button>
          <button  type="button">Delete</button>
          <button  type="button">Clear</button>
        </div>
      </div>
    </form>
  </div>
</div>

This is respective TypeScript file

import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';

@Component({
  selector: 'app-shopping-edit',
  templateUrl: './shopping-edit.component.html',
  styleUrls: ['./shopping-edit.component.css'],
})
export class ShoppingEditComponent implements OnInit {
  @ViewChild('nameInput') nameInputRef: ElementRef;
  @ViewChild('amountInput') amountInputRef: ElementRef;

  constructor() {}

  ngOnInit(): void {}
  onAddItem() {}
}

I get error to initialise the variables nameInputRef and amountInputRef. But I'm receiving these values from the form. How do I solve this?

CodePudding user response:

Typescript has no knowledge that you are grabbing those values from something defined in the template. Additionally, they will not be initialized until the view is initialized in the angular lifecycle, and you may potentially be attempting to access they when still undefined.

The answer to your question is to use the non null assertion operator !, as follows

export class ShoppingEditComponent implements OnInit {
 @ViewChild('nameInput') nameInputRef!: ElementRef;
 @ViewChild('amountInput') amountInputRef!: ElementRef;
}

However, be wary that this is misusing the operator, because, as mentioned, it is possible to access while it is still undefined.

A second method you could use is to expand the type to allow undefined

@ViewChild('nameInput') nameInputRef: ElementRef | undefined;

However when accessing any property, you would have to use the non null assertion operator

this.nameInputRef!.nativeElement

As an aside, If these elements are static within your component, (not subject to *ngIf or any conditional rendering) you can mark them as static. This will allow you to access them earlier in the component lifecycle, via ngOnInit.

@ViewChild('nameInput', { static: true }) nameInputRef: ElementRef;
@ViewChild('amountInput', { static: true }) amountInputRef: ElementRef;

I always mark a ViewChild as static if it meets these criteria so I have access to them as early in the lifecycle as possible

CodePudding user response:

this is probably because you are in stict mode. The solution would be to use non-null assertion (exclamation mark):

@ViewChild('nameInput') nameInputRef!: ElementRef;
@ViewChild('amountInput') amountInputRef!: ElementRef;
  • Related