3
votes

According to the Angular documentation for the @ViewChild decorator, one of the supported selectors is a provider with a string token. However when I define a provider using a string token in a child component and try and reference it using the @ViewChild decorator the view query is undefined.

I know it's possible to reference the provider using the read property with the component it's registered in as a selector, but how do I reference it using the string token as a selector alone?

I'm specifically talking about this type of string token selector (not a class provider, template reference variable, component, directive or a TemplateRef):

Any provider defined through a string token (e.g. @ViewChild('someToken') someTokenVal: any)

Here's an example:

@Component({
  selector: 'app-child',
  template: `<h1>Child</h1>`,
  providers: [{ provide: 'Token', useValue: 'Value' }]
})

export class ChildComponent{}

@Component({
  selector: 'app-parent',
  template: `<app-child></app-child>`
})

export class ParentComponent implements AfterViewInit{
  @ViewChild('Token') childToken: string;

  ngAfterViewinit(){
    console.log('token: ', childToken);
  }
}

This logs:

token: undefined
2
I think that is a regression in Ivy. It should work with ViewEngine if you disable Ivy. - yurzui
Thanks, @yurzui. I think I'll try it out. - the_coops
You were right @yurzui. It is a regression. It works if I disable Ivy. Thank you. I've answered the question but if you'd like, you could answer it and I'll mark it as the accepted answer. Thank you again. - the_coops
That's ok. I don't mind if you have already answered - yurzui

2 Answers

0
votes

As @yurzui had mentioned this is a regression in Ivy. This will not work. If you want to use a string token provider as a selector in @ViewChild you need to disable Ivy in the tsconfig.json file.

{
  "angularCompilerOptions": {
    "enableIvy": false,
  }
}
-1
votes

you can use ViewChild('stringToken') where stringToken is a template ref, not a selector

<div #stringToken></div>

also you can reference it by component or directive

@ViewChild(ChildComponent) child

in your case