Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does TypeScript ask me to initialise a property if I'm getting it's value from local reference?

I just started to learn Angular.

This is my custom component’s Template

    <div class="row">
  <div class="col-xs-12">
    <form action="">
      <div class="ro">
        <div class="col sm-5 form-group">
          <label for="name">Name</label>
          <input type="text" id="name" class="form-control" #nameInput />
        </div>
        <div class="col-sm-2 form-group">
          <label for="amount">Amount</label>
          <input type="number" id="amount" class="form-control" #amountInput />
        </div>
      </div>
      <div class="row">
        <div class="col-xs-12">
          <button class="btn btn-success" type="submit" (click)="onAddItem()">
            Add
          </button>
          <button class="btn btn-danger" type="button">Delete</button>
          <button class="btn btn-primary" type="button">Clear</button>
        </div>
      </div>
    </form>
  </div>
</div>

This is respective TypeScript file

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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?

>Solution :

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

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading