Angular 2 @ViewChild returns undefined
我看了几篇相关的文章和文档,但是似乎仍然无法从@ViewChild获得预期的行为。
最终,我试图设置div的滚动位置。这个元素不是组件,而是HTML中的普通div。
为此,我尝试使用@ViewChild来获取所需的DOM元素并设置其滚动值。 (顺便说一句,如果您知道一种无需@ViewChild(或jQuery)的更好的方法,将非常感谢您提供答案!)
目前,@ ViewChild仅返回未定义。通过一些虚拟检查:
-我在AfterViewInit中访问我的元素
-在此元素上,我没有任何其他指令,例如* ngIf或* ngFor。
这是控制器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import { Component, AfterViewInit, ViewChild, ElementRef } from '@angular/core'; @Component({ selector: 'portfolio-page', templateUrl: './portfolio-page.component.html', styleUrls: ['./portfolio-page.component.scss'] }) export class PortfolioPageComponent implements AfterViewInit{ @ViewChild('gallery-container') galleryContainer: ElementRef; ngAfterViewInit(){ console.log('My element: ' + this.galleryContainer); } } |
和模板:
1 2 | <img class='gallery-image' src='{{ coverPhotoVm }}' /> <img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' /> |
我的输出很简单:我的元素:未定义。
如您所见,我当前正在尝试通过ID访问元素,但是也尝试过使用类名。任何人都可以提供有关ViewChild选择器查询的更多详细信息吗?
我也看到了一些示例,其中使用哈希值'#'作为@ViewChild使用的选择符标识符--但这会导致#gallery-container对我造成模板解析错误。
我想不到这里可能有其他错误的地方。感谢所有帮助,谢谢!
此处提供完整代码:https://github.com/aconfee/KimbyArting/tree/master/client/KimbyArting/components/portfolio-page
尝试在模板中使用ref:
1 2 | <img class='gallery-image' src='{{ coverPhotoVm }}' /> <img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' /> |
并使用ref名称作为参数:
1 | @ViewChild('galleryContainer') galleryContainer: ElementRef; |
编辑
忘了提及如此声明的任何视图子级仅在视图初始化后可用。第一次发生这种情况是在
引用名称不得包含破折号,否则将不起作用
有时,如果在访问组件时尚未对其进行初始化,则会收到一条错误消息,指出子组件未定义。
但是,即使您访问AfterViewInit中的子组件,有时@ViewChild仍返回null。该问题可能是由* ngIf或其他指令引起的。
解决方案是使用@ViewChildren而不是@ViewChild并订阅在组件就绪时执行的更改订阅。
例如,如果要在父组件ParentComponent中访问子组件MyComponent。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import { Component, ViewChildren, AfterViewInit, QueryList } from '@angular/core'; import { MyComponent } from './mycomponent.component'; export class ParentComponent implements AfterViewInit { //other code emitted for clarity @ViewChildren(MyComponent) childrenComponent: QueryList<MyComponent>; public ngAfterViewInit(): void { this.childrenComponent.changes.subscribe((comps: QueryList<MyComponent>) => { // Now you can access the child component }); } } |
订阅变更
1 | @ViewChildren(MyComponent) childrenComponent: QueryList<MyComponent> |
确定有效,并结合
任何其他方法都会产生不可靠的结果,并且难以测试。
这是ViewChild使用DOM元素的.ts文件代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import { Component, AfterViewInit, ViewChild, ElementRef } from '@angular/core'; @Component({ selector: 'portfolio-page', templateUrl: './portfolio-page.component.html', styleUrls: ['./portfolio-page.component.scss'] }) export class PortfolioPageComponent implements AfterViewInit{ @ViewChild('galleryContainer') galleryContainer: ElementRef; ngAfterViewInit(){ console.log('My element: ' + this.galleryContainer); } } |
这是您的.html文件代码
1 2 | <img class='gallery-image' src='{{ coverPhotoVm }}' /> <img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' /> |
希望能帮助到你!
另一种可能的情况是,当您在有角度或离子性的框架中使用打字稿,并从具有类似于签名的javascript的函数中调用ViewChild元素时。请改用类似函数签名的打字稿(例如,使用粗箭头=>)。
例如
1 2 3 | accessViewChild(){ console.log(this.galleryContainer.nativeElement.innerHTML); } |
将显示未定义的打印
1 2 3 | accessViewChild = ()=>{ console.log(this.galleryContainer.nativeElement.innerHTML); } |
将打印内部html。
我今天有同样的问题。奇怪地使用
试试看:
1 2 3 | ngAfterViewInit(){ setTimeout(_ => console.log('My element: ' + this.galleryContainer), 0); } |
我有一个类似的问题。与您不同,我的
我通过将视图
1 2 3 4 5 6 | <textarea type ="text" id ="content" name ="content" #content [(ngModel)] ="article.content" required></textarea> |