コンポーネントテンプレートで定義された要素を取得する方法を誰かが知っていますか? Polymerは$
と$$
でそれを本当に簡単にします。
Angularでそれをどうやってやるのかと思っていました。
チュートリアルの例を見てください。
import {Component} from '@angular/core'
@Component({
selector:'display'
template:`
<input #myname(input)="updateName(myname.value)"/>
<p>My name : {{myName}}</p>
`
})
export class DisplayComponent {
myName: string = "Aman";
updateName(input: String) {
this.myName = input;
}
}
クラス定義内からp
またはinput
要素の参照を取得する方法を教えてください。
ElementRef
をインジェクトし、そこからquerySelector
などを使用する代わりに、ビュー内の要素に直接アクセスするための宣言的な方法を使用できます。
<input #myname>
@ViewChild('myname') input;
素子
ngAfterViewInit() {
console.log(this.input.nativeElement.value);
}
@ViewChildren('var1,var2,var3')
)。<ng-content>
投影要素)の中で行います。子孫
@ContentChildren()
は子孫も検索できる唯一のものです
@ContentChildren(SomeTypeOrVarName, {descendants: true}) someField;
{descendants: true}
をデフォルトにすべきですが、2.0.0の最終版ではなく、 バグと見なされます
これは2.0.1で修正されました。
読み取り
コンポーネントとディレクティブがある場合、read
パラメータはどのインスタンスを返すべきかを指定することを可能にします。
たとえば、デフォルトのViewContainerRef
ではなく動的に作成されたコンポーネントに必要なElementRef
@ViewChild('myname', { read: ViewContainerRef }) target;
変更を購読する
Viewの子はngAfterViewInit()
が呼び出されたときにのみ設定され、contentの子はngAfterContentInit()
が呼び出されたときにのみ設定されますが、クエリ結果の変更を購読する場合は、ngOnInit()
内で行う必要があります。
https://github.com/angular/angular/issues/9689#issuecomment-229247134
@ViewChildren(SomeType) viewChildren;
@ContentChildren(SomeType) contentChildren;
ngOnInit() {
this.viewChildren.changes.subscribe(changes => console.log(changes));
this.contentChildren.changes.subscribe(changes => console.log(changes));
}
直接DOMアクセス
dOM要素のみを照会できますが、コンポーネントやディレクティブインスタンスは照会できません。
export class MyComponent {
constructor(private elRef:ElementRef) {}
ngAfterViewInit() {
var div = this.elRef.nativeElement.querySelector('div');
console.log(div);
}
// for transcluded content
ngAfterContentInit() {
var div = this.elRef.nativeElement.querySelector('div');
console.log(div);
}
}
任意の投影コンテンツを取得する
変換されたコンテンツへのアクセス を参照してください。
コンポーネントのコンストラクタにインジェクトすることで、ElementRef
を介してDOM要素へのハンドルを取得できます。
constructor(myElement: ElementRef) { ... }
ドキュメント: https://angular.io/docs/ts/latest/api/core/index/ElementRef-class.html
import { Component, ElementRef, OnInit } from '@angular/core';
@Component({
selector:'display',
template:`
<input (input)="updateName($event.target.value)">
<p> My name : {{ myName }}</p>
`
})
class DisplayComponent implements OnInit {
constructor(public element: ElementRef) {
this.element.nativeElement // <- your direct element reference
}
ngOnInit() {
var el = this.element.nativeElement;
console.log(el);
}
updateName(value) {
// ...
}
}
最新バージョンで動作するように更新された例
ネイティブ要素の詳細については、 here
Angular 4 +:CSSセレクターでrenderer.selectRootElement
を使用して要素にアクセスします。
最初に電子メール入力を表示するフォームがあります。電子メールが入力されると、フォームが展開され、プロジェクトに関連する情報を引き続き追加できるようになります。ただし、それらが既存のクライアントではないnotの場合、フォームにはプロジェクト情報セクションの上に住所セクションが含まれます。
現在、データ入力部分はコンポーネントに分割されていないため、セクションは* ngIfディレクティブで管理されます。既存のクライアントの場合はプロジェクトノートフィールドにフォーカスを設定し、新規の場合は名フィールドにフォーカスを設定する必要があります。
私は成功せずに解決策を試しました。ただし、 this answerのUpdate 3は、最終的な解決策の半分を提供しました。他の半分は this スレッドでのMatteoNYの応答から来ました。結果は次のとおりです。
import { NgZone, Renderer } from '@angular/core';
constructor(private ngZone: NgZone, private renderer: Renderer) {}
setFocus(selector: string): void {
this.ngZone.runOutsideAngular(() => {
setTimeout(() => {
this.renderer.selectRootElement(selector).focus();
}, 0);
});
}
submitEmail(email: string): void {
// Verify existence of customer
...
if (this.newCustomer) {
this.setFocus('#firstname');
} else {
this.setFocus('#description');
}
}
私がしているのは要素にフォーカスを設定することだけなので、変更の検出について心配する必要はありません。そのため、Angularの外部でrenderer.selectRootElement
の呼び出しを実際に実行できます。新しいセクションをレンダリングする時間を与える必要があるため、要素の選択が試行される前にレンダリングスレッドが追いつくために、要素セクションはタイムアウトでラップされます。すべての設定が完了したら、基本的なCSSセレクターを使用して単純に要素を呼び出すことができます。
この例では主にフォーカスイベントを扱ったことを知っていますが、他のコンテキストでこれを使用できないのは私にとって難しいことです。
*ngIf
または*ngSwitchCase
内のコンポーネントインスタンスを取得しようとしている人のために、このトリックに従うことができます。
init
ディレクティブを作成します。
import {
Directive,
EventEmitter,
Output,
OnInit,
ElementRef
} from '@angular/core';
@Directive({
selector: '[init]'
})
export class InitDirective implements OnInit {
constructor(private ref: ElementRef) {}
@Output() init: EventEmitter<ElementRef> = new EventEmitter<ElementRef>();
ngOnInit() {
this.init.emit(this.ref);
}
}
コンポーネントをmyComponent
のような名前でエクスポートします
@Component({
selector: 'wm-my-component',
templateUrl: 'my-component.component.html',
styleUrls: ['my-component.component.css'],
exportAs: 'myComponent'
})
export class MyComponent { ... }
このテンプレートを使用してElementRef
AND MyComponent
インスタンスを取得します
<div [ngSwitch]="type">
<wm-my-component
#myComponent="myComponent"
*ngSwitchCase="Type.MyType"
(init)="init($event, myComponent)">
</wm-my-component>
</div>
TypeScriptでこのコードを使う
init(myComponentRef: ElementRef, myComponent: MyComponent) {
}
*/
import {Component,ViewChild} from '@angular/core' /*Import View Child*/
@Component({
selector:'display'
template:`
<input #myname (input) = "updateName(myname.value)"/>
<p> My name : {{myName}}</p>
`
})
export class DisplayComponent{
@ViewChild('myname')inputTxt:ElementRef; /*create a view child*/
myName: string;
updateName: Function;
constructor(){
this.myName = "Aman";
this.updateName = function(input: String){
this.inputTxt.nativeElement.value=this.myName;
/*assign to it the value*/
};
}
}
次のように、@ angular/coreからViewChildデコレータをインポートします。
<form #f="ngForm"> ... </form>
import { ViewChild } from '@angular/core';
class TemplateFormComponent {
@ViewChild('f') myForm: any;
.
.
.
}
これで、 'myForm'オブジェクトを使用して、クラス内のその中の任意の要素にアクセスできます。
ソース: https://codecraft.tv/courses/angular/forms/template-driven/ /
私はあなたがElementRef
を使っているなら、すべての答えが推奨するように、あなたはすぐにElementRef
が次のようなひどい型宣言をしているという問題に遭遇することを付け加えたいと思います
export declare class ElementRef {
nativeElement: any;
}
nativeElementがHTMLElement
であるブラウザ環境ではこれはばかげています。
これを回避するには、次の方法を使用できます。
import {Inject, ElementRef as ErrorProneElementRef} from '@angular/core';
interface ElementRef {
nativeElement: HTMLElement;
}
@Component({...}) export class MyComponent {
constructor(@Inject(ErrorProneElementRef) readonly elementRef: ElementRef) { }
}
すぐ次の兄弟を取得するには、これを使います
event.source._elementRef.nativeElement.nextElementSibling
リストからターゲット要素を選択します。同じ要素のリストから特定の要素を選択するのは簡単です。
コンポーネントコード:
export class AppComponent {
title = 'app';
listEvents = [
{'name':'item1', 'class': ''}, {'name':'item2', 'class': ''},
{'name':'item3', 'class': ''}, {'name':'item4', 'class': ''}
];
selectElement(item: string, value: number) {
console.log("item="+item+" value="+value);
if(this.listEvents[value].class == "") {
this.listEvents[value].class='selected';
} else {
this.listEvents[value].class= '';
}
}
}
htmlコード:
<ul *ngFor="let event of listEvents; let i = index">
<li (click)="selectElement(event.name, i)" [class]="event.class">
{{ event.name }}
</li>
CSSコード:
.selected {
color: red;
background:blue;
}