我试图访问原生元素,以便在点击另一个元素时专注于它(非常类似于html属性"对于" - 因为不能用于此类型的元素。
然而我收到错误:
TypeError:无法读取属性' nativeElement'未定义的
我尝试在ngAfterViewInit()
中调试native.lement中的nativeElement,以便加载但仍然会抛出错误。
我还在click事件处理程序中访问nativeElement,这样我可以在单击另一个元素时聚焦元素 - 这可能是什么问题,因为它在视图加载之前编译?
例如:
ngAfterViewInit() {
console.log(this.keywordsInput.nativeElement); // throws an error
}
focusKeywordsInput(){
this.keywordsInput.nativeElement.focus();
}
完整代码:
正在使用的html模板的相关部分:
<div id="keywords-button" class="form-group" (click)="focusKeywordsInput()">
<input formControlName="keywords" id="keywords-input" placeholder="KEYWORDS (optional)"/>
<div class="form-control-icon" id="keywords-icon"></div>
</div>
component.ts:
import { Component, OnInit, AfterViewInit, ViewChild, ElementRef } from '@angular/core';
import { REACTIVE_FORM_DIRECTIVES,
FormGroup,
FormBuilder,
Validators,
ControlValueAccessor
} from '@angular/forms';
import { NumberPickerComponent } from './number-picker.component';
import { DistanceUnitsComponent } from './distance-units.component';
import { MapDemoComponent } from '../shared/map-demo.component';
import { AreaComponent } from './area-picker.component';
import { GoComponent } from './go.component';
import { HighlightDirective } from '../highlight.directive';
@Component({
selector: 'find-form',
templateUrl: 'app/find-page/find-form.component.html',
styleUrls: ['app/find-page/find-form.component.css'],
directives: [REACTIVE_FORM_DIRECTIVES,
NumberPickerComponent,
DistanceUnitsComponent,
MapDemoComponent,
AreaComponent,
GoComponent]
})
export class FindFormComponent implements OnInit, AfterViewInit {
findForm: FormGroup;
submitted: boolean; // keep track on whether form is submitted
events: any[] = []; // use later to display form changes
@ViewChild('keywords-input') keywordsInput;
//comment
constructor(private formBuilder: FormBuilder, el: ElementRef) {}
ngOnInit() {
this.findForm = this.formBuilder.group({
firstname: ['', [ Validators.required, Validators.minLength(5) ] ],
lastname: ['', Validators.required],
keywords: [],
area: ['', Validators.required],
address: this.formBuilder.group({
street: [],
zip: [],
city: []
})
});
this.findForm.valueChanges.subscribe(data => console.log('form changes', data));
}
ngAfterViewInit() {
console.log(this.keywordsInput.nativeElement); // throws an error
}
focusKeywordsInput(){
this.keywordsInput.nativeElement.focus();
}
save(isValid: boolean) {
this.submitted = true;
// check if model is valid
// if valid, call API to save customer
console.log(isValid);
}
}
完整的html模板(可能无关紧要):
<form class="text-uppercase" [formGroup]="findForm" (ngSubmit)="save(findForm.value, findForm.valid)">
<div class="row is-heading">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group">
<h2 class="search-filter-heading heading m-x-auto">find vegan</h2>
</div>
</div>
<div class="row has-error-text">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group btn-group" style="height:64px;">
<div style="position: relative; display: inline-block; width: 100%;">
<multiselect #multiselect></multiselect>
</div>
</div>
</div>
<div class="row error-text" [style.display]="multiselect.selectedCategories.length < 1 && submitted ? 'block' : 'none'">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 form-group input-group btn-group">
<small>Please select at least 1 category.</small>
</div>
</div>
<div class="row is-heading">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group">
<h2 class="search-filter-heading heading m-x-auto">within</h2>
</div>
</div>
<div class="row">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group btn-group" style="height:64px;">
<div style="position: relative; display: inline-block;">
<number-picker #numberPicker></number-picker>
</div>
<distance-units></distance-units>
</div>
</div>
<div class="row is-heading">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group">
<h2 class="search-filter-heading heading m-x-auto">of</h2>
</div>
</div>
<div class="row has-error-text">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group btn-group" style="height:64px;">
<div style="position: relative; display: inline-block; width: 100%;">
<my-area></my-area>
</div>
</div>
</div>
<div class="row error-text" [style.display]="multiselect.selectedCategories.length < 1 && submitted ? 'block' : 'none'">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 form-group input-group btn-group">
<small [hidden]="findForm.controls.firstname.valid || (findForm.controls.firstname.pristine && !submitted)">Please enter an area.</small>
</div>
</div>
<div class="row is-heading">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group">
<h2 class="search-filter-heading heading m-x-auto">keywords</h2>
</div>
</div>
<div class="row form-group">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group btn-group" style="height:64px;">
<div style="position: relative; display: inline-block; width: 100%;">
<div id="keywords-button" class="form-group" (click)="focusKeywordsInput()">
<input formControlName="keywords" id="keywords-input" placeholder="KEYWORDS (optional)"/>
<div class="form-control-icon" id="keywords-icon"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group btn-group" style="height:64px;">
<div style="position: relative; display: inline-block; width: 100%;">
<go></go>
</div>
</div>
</div>
</form>
答案 0 :(得分:33)
@ViewChild('keywords-input') keywordsInput;
与id="keywords-input"
id="keywords-input"
应该是模板变量:
#keywordsInput
请注意,应使用驼峰大小写,因为模板引用名称中不允许-
。
@ViewChild()
支持模板变量的名称为string:
@ViewChild('keywordsInput') keywordsInput;
或组件或指令类型:
@ViewChild(MyKeywordsInputComponent) keywordsInput;
另见https://stackoverflow.com/a/35209681/217408
<强>提示:强>
在调用keywordsInput
之前未设置ngAfterViewInit()
答案 1 :(得分:12)
如果您的目标元素在隐藏元素内,您还将收到此错误。如果这是您的HTML:
<div *ngIf="false">
<span #sp>Hello World</span>
</div>
您的@ViewChild('sp') sp
是未定义的。
在这种情况下,请不要使用*ngIf
。
使用类来显示/隐藏隐藏的元素。
<div [class.show]="shouldShow">...</div>
答案 2 :(得分:10)
接受的答案在所有方面都是正确的,当我无法在我的一个应用程序组件中获得Google Map渲染后,我偶然发现了这个线程。
现在,如果您使用的是最新的角度版本(即7+),则必须处理以下 ViewChild 声明,即
@ViewChild(selector: string | Function | Type<any>, opts: {
read?: any;
static: boolean;
})
现在,有趣的部分是静态值,根据定义,它是
现在用于渲染地图,我使用以下代码,
@ViewChild('map', { static: true }) mapElement: any;
map: google.maps.Map;
答案 3 :(得分:4)
当您尝试定位包装在条件中的元素时,会发生此错误。
因此,在这里,如果我使用ngIf代替[hidden],它将给我TypeError:无法读取未定义的属性'nativeElement'
因此,请使用[hidden],class.show或class.hide代替* ngIf。
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300" viewBox="-10 -10 100 100">
<g fill="rgba(0,0,72)">
<circle class="circle" cx="191" cy="90" r="2" />
<circle cx="5" cy="5" r="2" />
<circle cx="10" cy="10" r="2" />
<circle cx="5" cy="20" r="2" />
<circle cx="10" cy="20" r="2" />
<circle cx="20" cy="20" r="2" />
<circle cx="30" cy="20" r="2" />
<circle cx="40" cy="20" r="2" />
<circle cx="50" cy="20" r="2" />
<circle cx="60" cy="20" r="2" />
<circle cx="30" cy="30" r="2" />
<circle xmlns="http://www.w3.org/2000/svg" cx="35" cy="10" r="3" fill="rgba(204,153,24)" />
<circle cx="40" cy="40" r="2" />
<circle cx="50" cy="50" r="2" />
<circle cx="60" cy="60" r="2" />
<circle cx="60" cy="5" r="2" />
<circle cx="60" cy="10" r="2" />
<circle cx="60" cy="20" r="2" />
<circle cx="60" cy="30" r="2" />
<circle cx="60" cy="40" r="2" />
<circle cx="60" cy="50" r="2" />
</g>
</svg>
答案 4 :(得分:1)
这很简单:导入此目录
import {Component, Directive, Input, ViewChild} from '@angular/core';
答案 5 :(得分:1)
我遇到了类似的问题,但就我而言,我试图读取 nativeElement
方法中的 ngOnInit
:
@ViewChild('userNameInput') userNameInput: ElementRef<HTMLInputElement>;
...
ngOnInit(): void {
this.userNameInput.nativeElement.focus();
}
我已更改为 ngAfterViewInit
并且一切正常:
@ViewChild('userNameInput') userNameInput: ElementRef<HTMLInputElement>;
...
ngAfterViewInit(): void {
this.userNameInput.nativeElement.focus();
}
答案 6 :(得分:0)
发生的事情是,在加载DOM之前调用这些元素时,会出现此类错误。始终使用:
window.onload = function(){
this.keywordsInput.nativeElement.focus();
}
答案 7 :(得分:0)
有时,当您尝试定位包装在条件中的元素时,会发生此错误,例如:
<div *ngIf="canShow"> <p #target>Targeted Element</p></div>
在此代码中,如果canShow
在渲染时为false,则Angular将无法获取该元素,因为它不会被渲染,因此会出现错误。
解决方案之一是在元素上使用display: hidden
而不是*ngIf
,以便呈现元素但隐藏元素,直到满足条件为止。
了解更多over at Github
答案 8 :(得分:-1)
像下面那样初始化Canvas可以用于TypeScript / Angular解决方案。
const canvas = <HTMLCanvasElement> document.getElementById("htmlElemId");
const context = canvas.getContext("2d");