318

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.

kian
  • 1,449
  • 2
  • 13
  • 21
stack overflow
  • 3,205
  • 2
  • 9
  • 7

11 Answers11

625

In Angular 8 , ViewChild takes 2 parameters

 @ViewChild(ChildDirective, {static: false}) Component
Jensen
  • 6,615
  • 1
  • 10
  • 12
  • 10
    can you please mark it as accepted? From Angular docs: static - whether or not to resolve query results before change detection runs (i.e. return static results only). If this option is not provided, the compiler will fall back to its default behavior, which is to use query results to determine the timing of query resolution. If any query results are inside a nested view (e.g. *ngIf), the query will be resolved after change detection runs. Otherwise, it will be resolved before change detection runs. – Jensen Jun 21 '19 at 13:35
  • 13
    You should add that to the answer if you want him to accept your answer as the best one – Sytham Sep 16 '19 at 13:11
  • 19
    Note: to keep the behavior you had in Angular 7, you need to specify `{ 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` – evilkos Sep 23 '19 at 08:40
  • 14
    If the element needs to be available during ngOnInit, then static needs to be `true`, but if it can wait until after the init it can be `false`, which means it won't be available until ngAfterViewInit/ngAfterContentInit. – Armen Zakaryan Dec 16 '19 at 04:53
  • I got this error as well, but still need to know what happend if static: true? Thanks – Tarmizi Hamid Jun 27 '20 at 07:54
114

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}

Reza
  • 18,865
  • 13
  • 88
  • 163
  • In one of the articles you linked to, they show syntax like `@ContentChild('foo', {static: false}) foo !: ElementRef;`. I'm curious about the exclamation mark. Is that something new with Angular 8 too? – Konrad Viltersten Dec 01 '19 at 20:00
  • 1
    @KonradViltersten see this https://stackoverflow.com/a/56950936/2279488 – Reza Dec 02 '19 at 14:32
44

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

Fouad Boukredine
  • 1,495
  • 14
  • 18
Adrita Sharma
  • 21,581
  • 10
  • 69
  • 79
9

it is because view child require two argument try like this

@ViewChild('nameInput', { static: false, }) nameInputRef: ElementRef;

@ViewChild('amountInput', { static: false, }) amountInputRef: ElementRef;

paras shah
  • 861
  • 2
  • 9
  • 23
4

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.

Pinki Dhakad
  • 150
  • 5
2

Try this in angular 8.0:

@ViewChild('result',{static: false}) resultElement: ElementRef;
prosoitos
  • 6,679
  • 5
  • 27
  • 41
SoNu
  • 21
  • 5
  • 1
    this question is one year old, but you has reason, in Angular 8.0 was neccesary {static:true/false}. In Angular 9 and 10 this argument is optional – Eliseo Sep 26 '20 at 20:16
1

Regex for replacing all via IDEA (tested with Webstorm)

Find: \@ViewChild\('(.*)'\)

Replace: \@ViewChild\('$1', \{static: true\}\)

Torsten Simon
  • 348
  • 4
  • 10
1

you should use second argument with ViewChild like this:

@ViewChild("eleDiv", { static: false }) someElement: ElementRef;
Hammad Ahmad
  • 184
  • 1
  • 6
1

Use this

@ViewChild(ChildDirective, {static: false}) Component

1

In Angular 8, ViewChild has another param

@ViewChild('nameInput', {static: false}) component

I resolved my issue like below

@ViewChild(MatSort, {static: false}) sort: MatSort;

Manoj Tyagi
  • 169
  • 2
  • 3
-5

That also resolved my issue.

@ViewChild('map', {static: false}) googleMap;
Arsman Ahmad
  • 2,000
  • 1
  • 26
  • 34
Helmar Bachle
  • 49
  • 1
  • 1
  • 9