[解決済み] @viewChildが機能しない - プロパティnativeElementがundefinedで読み込めない
質問
他の要素がクリックされたときに、その要素にフォーカスするためにネイティブ要素にアクセスしようとしています(html属性の"for"のようなもの - forはこのタイプの要素には使用できません)。
しかし、エラーが発生します。
TypeError: 未定義のプロパティ 'nativeElement' を読み取ることができません。
にある nativeElement を console.log してみます。
ngAfterViewInit()
を読み込むようにしましたが、まだエラーがスローされます。
また、クリックイベントハンドラーで 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>
解決方法は?
@ViewChild('keywords-input') keywordsInput;
とは一致しません。
id="keywords-input"
id="keywords-input"
は、代わりにテンプレート変数にする必要があります。
#keywordsInput
は、キャメルケースを使用することに注意してください。
-
は、テンプレート参照名には使用できません。
@ViewChild()
は、テンプレート変数の名前を文字列としてサポートします。
@ViewChild('keywordsInput') keywordsInput;
またはコンポーネントやディレクティブの種類を指定します。
@ViewChild(MyKeywordsInputComponent) keywordsInput;
参照 https://stackoverflow.com/a/35209681/217408
ヒント
keywordsInput
が設定される前に
ngAfterViewInit()
が呼び出されます。
関連
-
[解決済み] @viewChildが機能しない - プロパティnativeElementがundefinedで読み込めない
-
[解決済み】エラー。どのルートにもマッチしません。URLセグメント: - Angular 2
-
[解決済み] テンプレートパースエラーです。'mat-icon' は既知の要素ではありません。
-
[解決済み] Angular2 Router: Error: Cannot find primary outlet to load 'InboxComponent'.
-
[解決済み] Angular 2の@ViewChildアノテーションがundefinedを返す
-
[解決済み] Angular "未定義のプロパティ 'subscribe' を読み取ることができません".
-
[解決済み] Angular2 Final Release - 「Error: AngularにはZone.jsのプロリフィルが必要です"
-
[解決済み] 安全でない値」の例外を発生させずに <iframe src="..."> を設定するにはどうしたらよいですか?
-
[解決済み] switchの使用時に「ステートメントはif文でフィルタリングされなければならない」というtslintのクレームが発生する。
-
[解決済み] Angular2 Selectorが、ネストしたComponentのどの要素にもマッチしない。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] @viewChildが機能しない - プロパティnativeElementがundefinedで読み込めない
-
[解決済み】Angular2エラー。exportAs "が "ngForm "に設定されたディレクティブは存在しません。
-
[解決済み】angularモジュールでModule has no exported memberエラー
-
[解決済み] Angular 4: コンポーネントファクトリが見つかりません。@NgModule.entryComponents に追加しましたか?
-
[解決済み] NullInjectorError: MatDialogRef 用のプロバイダがありません
-
[解決済み] Angular 2 ルーターベースなし href = "/stock/stock_detail.html?
-
[解決済み] なぜ mat-tables matRowDef は 2 つの変数を含むのですか?
-
[解決済み] Angular 2の「コンポーネント」は既知の要素ではありません。
-
[解決済み] Angular 4 - "BrowserAnimationsModule "または "NoopAnimationsModule "のいずれかをアプリケーションに組み込んでください。
-
[解決済み] コンポーネントテンプレートで要素を選択するには?