Angular 2 @ViewChild returns 未定义
Angular 2 @ViewChild returns undefined
我查看了几篇相关的帖子和文档,但似乎仍然无法从@ViewChild 获得预期的行为。
最终,我尝试设置 div 的滚动位置。此元素不是组件,而是我的 HTML 中的普通 div。
为此,我尝试使用@ViewChild 来获取我需要的DOM 元素,并设置其滚动值。 (顺便说一句,如果您知道在没有@ViewChild(或jQuery)的情况下完成此操作的更好方法,将不胜感激!)
目前,@ViewChild 仅 returns 未定义。通过一些虚拟检查:
- 我在 AfterViewInit 中访问我的元素
- 我在此元素上没有任何其他指令,例如 *ngIf 或 *ngFor。
这是控制器:
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);
}
}
和模板:
<div id='gallery-container' class='gallery-image-container'>
<div class='gallery-padding'></div>
<img class='gallery-image' src='{{ coverPhotoVm }}' />
<img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' />
</div>
我的输出很简单:我的元素:未定义。
如您所见,我目前正尝试通过 ID 访问元素,但也尝试了 class 名称。谁能提供有关 ViewChild 选择器查询所期望的内容的更多详细信息?
我也看到过使用散列“#”作为@ViewChild 使用的选择器标识符的示例 -- -- 但这会导致我使用#gallery-container 时出现模板解析错误。
我想不出这里还有什么可能是错误的。感谢所有帮助,谢谢!
此处提供完整代码:https://github.com/aconfee/KimbyArting/tree/master/client/KimbyArting/components/portfolio-page
尝试在您的模板中使用引用:
<div id='gallery-container' #galleryContainer class='gallery-image-container'>
<div class='gallery-padding'></div>
<img class='gallery-image' src='{{ coverPhotoVm }}' />
<img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' />
</div>
并使用 ref 名称作为参数:
@ViewChild('galleryContainer') galleryContainer: ElementRef;
编辑
忘了说这样声明的任何子视图只有在视图初始化后才可用。第一次发生这种情况是在 ngAfterViewInit
(导入并实现 AfterViewInit
接口)。
ref 名称不能包含破折号,否则这将不起作用
有时,如果组件在您访问时尚未初始化,您会收到一个错误,指出子组件未定义。
但是,即使您在AfterViewInit 中访问子组件,有时@ViewChild 仍然返回null。该问题可能是由 *ngIf 或其他指令引起的。
解决方案是使用@ViewChildren 代替@ViewChild 并订阅组件准备就绪时执行的更改订阅。
比如在父组件ParentComponent中你想访问子组件MyComponent。
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
});
}
}
正在订阅
上的更改
@ViewChildren(MyComponent) childrenComponent: QueryList<MyComponent>
确认工作,结合 setTimeout()
和 notifyOnChanges()
并仔细 null
检查。
任何其他方法都会产生不可靠的结果并且难以测试。
我遇到了类似的问题。与你不同,我的 @ViewChild
返回了一个有效的 ElementRef
,但是当我尝试访问它的 nativeElement
时,它是 undefined
。
我通过将视图 id
设置为 #content
而不是 #content = "ngModel"
.
解决了这个问题
<textarea type = "text"
id = "content"
name = "content"
#content
[(ngModel)] = "article.content"
required></textarea>
另一种可能的情况是,当您在 angular 或离子框架中使用打字稿并从具有 javascript 之类签名的函数调用 ViewChild 元素时。请改用函数签名之类的打字稿(例如,使用粗箭头 =>)。
例如
accessViewChild(){
console.log(this.galleryContainer.nativeElement.innerHTML);
}
会显示 print undefined 但是
accessViewChild = ()=>{
console.log(this.galleryContainer.nativeElement.innerHTML);
}
将打印内部 html.
这是 ViewChild
使用 DOM 元素的 .ts 文件代码
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 文件代码
<div #galleryContainer class='gallery-image-container'>
<div class='gallery-padding'></div>
<img class='gallery-image' src='{{ coverPhotoVm }}' />
<img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' />
</div>
希望对您有所帮助!
我查看了几篇相关的帖子和文档,但似乎仍然无法从@ViewChild 获得预期的行为。
最终,我尝试设置 div 的滚动位置。此元素不是组件,而是我的 HTML 中的普通 div。
为此,我尝试使用@ViewChild 来获取我需要的DOM 元素,并设置其滚动值。 (顺便说一句,如果您知道在没有@ViewChild(或jQuery)的情况下完成此操作的更好方法,将不胜感激!)
目前,@ViewChild 仅 returns 未定义。通过一些虚拟检查: - 我在 AfterViewInit 中访问我的元素 - 我在此元素上没有任何其他指令,例如 *ngIf 或 *ngFor。
这是控制器:
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);
}
}
和模板:
<div id='gallery-container' class='gallery-image-container'>
<div class='gallery-padding'></div>
<img class='gallery-image' src='{{ coverPhotoVm }}' />
<img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' />
</div>
我的输出很简单:我的元素:未定义。
如您所见,我目前正尝试通过 ID 访问元素,但也尝试了 class 名称。谁能提供有关 ViewChild 选择器查询所期望的内容的更多详细信息?
我也看到过使用散列“#”作为@ViewChild 使用的选择器标识符的示例 -- -- 但这会导致我使用#gallery-container 时出现模板解析错误。
我想不出这里还有什么可能是错误的。感谢所有帮助,谢谢!
此处提供完整代码:https://github.com/aconfee/KimbyArting/tree/master/client/KimbyArting/components/portfolio-page
尝试在您的模板中使用引用:
<div id='gallery-container' #galleryContainer class='gallery-image-container'>
<div class='gallery-padding'></div>
<img class='gallery-image' src='{{ coverPhotoVm }}' />
<img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' />
</div>
并使用 ref 名称作为参数:
@ViewChild('galleryContainer') galleryContainer: ElementRef;
编辑
忘了说这样声明的任何子视图只有在视图初始化后才可用。第一次发生这种情况是在 ngAfterViewInit
(导入并实现 AfterViewInit
接口)。
ref 名称不能包含破折号,否则这将不起作用
有时,如果组件在您访问时尚未初始化,您会收到一个错误,指出子组件未定义。
但是,即使您在AfterViewInit 中访问子组件,有时@ViewChild 仍然返回null。该问题可能是由 *ngIf 或其他指令引起的。
解决方案是使用@ViewChildren 代替@ViewChild 并订阅组件准备就绪时执行的更改订阅。
比如在父组件ParentComponent中你想访问子组件MyComponent。
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
});
}
}
正在订阅
上的更改@ViewChildren(MyComponent) childrenComponent: QueryList<MyComponent>
确认工作,结合 setTimeout()
和 notifyOnChanges()
并仔细 null
检查。
任何其他方法都会产生不可靠的结果并且难以测试。
我遇到了类似的问题。与你不同,我的 @ViewChild
返回了一个有效的 ElementRef
,但是当我尝试访问它的 nativeElement
时,它是 undefined
。
我通过将视图 id
设置为 #content
而不是 #content = "ngModel"
.
<textarea type = "text"
id = "content"
name = "content"
#content
[(ngModel)] = "article.content"
required></textarea>
另一种可能的情况是,当您在 angular 或离子框架中使用打字稿并从具有 javascript 之类签名的函数调用 ViewChild 元素时。请改用函数签名之类的打字稿(例如,使用粗箭头 =>)。 例如
accessViewChild(){
console.log(this.galleryContainer.nativeElement.innerHTML);
}
会显示 print undefined 但是
accessViewChild = ()=>{
console.log(this.galleryContainer.nativeElement.innerHTML);
}
将打印内部 html.
这是 ViewChild
使用 DOM 元素的 .ts 文件代码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 文件代码
<div #galleryContainer class='gallery-image-container'>
<div class='gallery-padding'></div>
<img class='gallery-image' src='{{ coverPhotoVm }}' />
<img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' />
</div>
希望对您有所帮助!