When trying ViewChild I am getting the error. Error is "An argument for 'opts' was not provided."
Both @ViewChild is giving the error.
import { Component, OnInit, ElementRef, ViewChild, Output, EventEmitter } from '@angular/core';
import { Ingredient } from 'src/app/shared/ingredient.model';
@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;
@Output() ingredientAdded = new EventEmitter<Ingredient>();
constructor() {}
ngOnInit() {
}
onAddItem() {
const ingName = this.nameInputRef.nativeElement.value;
const ingAmount = this.amountInputRef.nativeElement.value;
const newIngredient = new Ingredient(ingName, ingAmount);
this.ingredientAdded.emit(newIngredient);
}
}
ts(11,2): error TS2554: Expected 2 arguments, but got 1.
In Angular 8 , ViewChild takes 2 parameters
@ViewChild(ChildDirective, {static: false}) Component
Angular 8
In Angular 8, ViewChild has another param
@ViewChild('nameInput', {static: false}) component : Component
You can read more about it here and here
Angular 9 & Angular 10
In Angular 9
default value is static: false
, so doesn't need to provide param unless you want to use {static: true}
@ContentChild('foo', {static: false}) foo !: ElementRef;
. I'm curious about the exclamation mark. Is that something new with Angular 8 too?
In Angular 8 , ViewChild
takes 2 parameters:
Try like this:
@ViewChild('nameInput', { static: false }) nameInputRef: ElementRef;
Explanation:
{ static: false }
If you set static false, the child component ALWAYS gets initialized after the view initialization in time for the ngAfterViewInit/ngAfterContentInit
callback functions.
{ static: true}
If you set static true, the child component initialization will take place at the view initialization at ngOnInit
By default you can use { static: false }
. If you are creating a dynamic view and want to use the template reference variable, then you should use { static: true}
For more info, you can read this article
Working Demo
In the demo, we will scroll to a div using template reference variable.
@ViewChild("scrollDiv", { static: true }) scrollTo: ElementRef;
With { static: true }
, we can use this.scrollTo.nativeElement
in ngOnInit
, but with { static: false }
, this.scrollTo
will be undefined
in ngOnInit
, so we can access in only in ngAfterViewInit
it is because view child require two argument try like this
@ViewChild('nameInput', { static: false, }) nameInputRef: ElementRef; @ViewChild('amountInput', { static: false, }) amountInputRef: ElementRef;
In Angular 8, ViewChild always takes 2 param, and second params always has static: true or static: false
You can try like this:
@ViewChild('nameInput', {static: false}) component
Also,the static: false
is going to be the default fallback behaviour in Angular 9.
What are static false/true: So as a rule of thumb you can go for the following:
{ static: true } needs to be set when you want to access the ViewChild in ngOnInit. { static: false } can only be accessed in ngAfterViewInit. This is also what you want to go for when you have a structural directive (i.e. *ngIf) on your element in your template.
Try this in angular 8.0:
@ViewChild('result',{static: false}) resultElement: ElementRef;
Regex for replacing all via IDEA (tested with Webstorm)
Find: \@ViewChild\('(.*)'\)
Replace: \@ViewChild\('$1', \{static: true\}\)
you should use second argument with ViewChild like this:
@ViewChild("eleDiv", { static: false }) someElement: ElementRef;
Use this
@ViewChild(ChildDirective, {static: false}) Component
In Angular 8, ViewChild has another param
@ViewChild('nameInput', {static: false}) component
I resolved my issue like below
@ViewChild(MatSort, {static: false}) sort: MatSort;
That also resolved my issue.
@ViewChild('map', {static: false}) googleMap;
Success story sharing
{ static: true }
.ng update
will help you do this automatically where needed. Or, if you've already upgraded your dependencies to Angular 8, this command will help migrate your code:ng update @angular/core --from 7 --to 8 --migrate-only
true
, but if it can wait until after the init it can befalse
, which means it won't be available until ngAfterViewInit/ngAfterContentInit.