-
-
Notifications
You must be signed in to change notification settings - Fork 239
Description
Overview
Angular is unable to match queries against class names for built-in {N} components. The following basic view query will fail and return undefined.
@Component({
selector: 'comp-1',
template: `<GridLayout></GridLayout>`
})
class CompOne implements AfterViewInit {
@ViewChild(GridLayout) ref: GridLayout;
ngAfterViewInit() {
console.log("child ref is -> " + this.ref);
}
}
Reproduction
https://play.nativescript.org/?id=ezJW7O_-Yw0QbA-pQC280&template=play-ng
Why it fails
The best way I've had it explained was by @vakrilov in Slack: The built-in {N} components are similar to the native elements in a Browser (HTMLButtonElement, HTMLInputElement, etc.) You would not query for @ViewChild(HTMLInputElement) in the Browser, so why would you query for @ViewChild(Image) or @ViewChild(Label) in {N}+Angular?
Problems
The browser element analogy makes sense as a way to explain the limitation, but it breaks down under scrutiny from a developer experience point of view. In the browser case all of the built-in elements are named consistently HTML[name]Element, so you know immediately by name if an element can be queried for using its class name. In the {N} case the built-ins are called "components" in the docs, and have no hint in their names (Image, Label, etc.) to let you know they're built-in so you have to think about it each time you write a view query.
The point I'm making here is subtle, and I understand that, but I think it's worth discussing as it has the potential to address a common stumbling block and/or point of confusion for developers getting started with {N}+Angular.
Solutions
I see at least a few ways you could try to address this:
-
Use developer education by way of tutorials and documentation updates to make this limitation clear and understandable to users. I suspect this is a challenging way to go about things because it's hard to get people to read things before they go ask someone else for help.
-
Update built-in names with common convention to make it more obvious that they're native elements. I don't seriously think anyone would attempt this, but it's an option.
-
Throw an error when a developer writes a query for a built-in element. This would give developers timely feedback and keep them moving without lifting the query restriction. I don't know how realistic this is because the ViewQuery stuff is pretty buried in angular's guts and hooking it might not be straightforward.
-
Declare built-ins as components to Angular. I believe that {N} has all the information it needs to do this. It already has a hook for declaring components
registerElementwhich could potentially be used to decorate the view classes with@Directiveand add them to an Angular module that is imported. I have verified that built-ins are queried if they're decorated and declared as components. You could even go further to map all their {N} declared properties as@Inputs. -
Keep this issue closed, and maybe it's a good reference for when people stumble.