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;