How to make Angular understand that view child is of a specific type, not a general ElementRef?

35 views Asked by At

I have an element in my HTML like this (inspiration from this blog). While the user types, I'm showing successive filtrations in a list to pick from. Once the user clicks on that component, I want to update the value typed in the search box below and replace it with the full name available in the clicked item.

<input #userSelector (keyup)="onKeyUpUser($event)">

In order to communicate easily, I have set up a view child as shown below. Then, in the handler of the click, I set the value picked.

@ViewChild("userSelector") userSelector: ElementRef;
...
onClickUser(user: User) {
  this.userSelector.nativeElement.value = user.name;
  ...
}

This works as expected. Now, I wanted to be clever and realized that the view child is not only a general ElementRef but, in fact, HTMLInputElement, so I replaced the code like this.

@ViewChild("userSelector") userSelector: HTMLInputElement;
...
onClickUser(user: User) {
  this.userSelector.value = user.name;
  ...
}

To my surprise, it doesn't update the contents visible on the screen. In the console, I can see that the field value has appeared and has the value I assigned. But it won't show. It's the same element, so I'm confused why this happens.

What's the reason this occurs and (how) can I use the more specific type of the view child (hence allowing to avoid the detour through nativeElement to get to the value field?

1

There are 1 answers

3
Francesco Moro On BEST ANSWER

It is indeed correct to type the property decorated with ElementRef, but it is just not enough: just add the generic type to ElementRef.

@ViewChild("userSelector") userSelector: ElementRef<HTMLInputElement>;
...
onClickUser(user: User) {
  this.userSelector.nativeElement.value = user.name;
  ...
}

The ViewChild decorator give you access to a typed ElementRef (in this case of HTMLInputElement => ElementRef<HTMLInputElement>), not to an HTMLInputElement one!

If you want to observe a child component, you will directly get the component instance (so, no need to type the property to ElementRef<MyChildComponent>>). In that case you can just do the following:

@ViewChild(MyComponent) myComponent?: MyComponent;