以下の更新を参照してください
まだ Angular2 Beta で遊んでいますが、「エディター」コンポーネント テンプレートに Ace エディターをラップするディレクティブが含まれるシナリオを実装しようとしています。したがって、「エディター」コンポーネントは Ace ラッパー ディレクティブの親であり、ディレクティブからコードを取得するか、コードを設定したいと考えています。
ディレクティブだけでも問題なく動作しますが、このコンポーネントに含めると何も表示されません。ブラウザのコンソールにエラーは表示されません。このPlunkerで再現を見つけることができます: http://plnkr.co/edit/kzclJLIX6hRMWa14A0Pb。
私の実装ではace.directive
、Ace エディターをラップするディレクティブにtext
プロパティとtextChanged
イベントがあります。
import {Component,Directive,EventEmitter,ElementRef} from 'angular2/core';
declare var ace: any;
@Directive({
selector: "ace-editor",
inputs: [
"text"
],
outputs: [
"textChanged"
]
})
export class AceDirective {
private editor : any;
private settingText : boolean;
public textChanged: EventEmitter<string>;
set text(s: string) {
let sOld = this.editor.getValue();
if (sOld === s) return;
this.settingText = true;
this.editor.setValue(s);
this.editor.clearSelection();
this.editor.focus();
this.settingText = false;
}
constructor(elementRef: ElementRef) {
var dir = this;
this.textChanged = new EventEmitter<string>();
let el = elementRef.nativeElement;
this.editor = ace.edit(el);
this.editor.on("change", (e) => {
if (dir.settingText) return;
dir.textChanged.next(dir.editor.getValue());
});
}
}
editor.component
コンポーネントはディレクティブを使用します。このディレクティブには、編集xml
中の XML コードを表すプロパティがあります。そのテンプレートには、次のようなディレクティブが含まれています。
<ace-editor id="editor" [text]="xml" (textChanged)="onXmlChanged()"></ace-editor>
つまり、ディレクティブのtext
プロパティは親コンポーネントのプロパティにバインドされxml
、ディレクティブのtextChanged
イベントは親の
onXmlChanged
関数によって処理されます。
これは双方向のデータバインディングです。私の知る限り、次のことも試すことができます。
<ace-editor id="editor" [(ngModel)]="xml"></ace-editor>
エディタのコードは次のとおりです。
import {Component,EventEmitter} from "angular2/core";
import {AceDirective} from "./ace.directive";
@Component({
selector: "mit-editor",
directives: [AceDirective],
template: `<div>
<ace-editor id="editor" [text]="xml" (textChanged)="onXmlChanged()"></ace-editor>
</div>
`,
inputs: [
"xml"
]
})
export class EditorComponent {
public xml: string;
constructor() {
this.xml = "";
}
public onXmlChanged(xml: string) {
this.xml = xml;
}
}
更新 #1 何らかの理由で、Plunker は既存のファイル以外の .ts ファイルを変換およびロードしないため、ローカルでトラブルシューティングを続けました。
$event
質問に関しては、テンプレートの呼び出しに引数を追加する必要があることがわかりました (私のコメントを参照してください)。私のディレクティブは次のとおりです。
import {Component,Directive,EventEmitter,ElementRef} from 'angular2/core';
declare var ace: any;
@Directive({
selector: "ace-editor",
inputs: [
"text"
],
outputs: [
"textChanged"
]
})
export class AceDirective {
private editor : any;
public textChanged: EventEmitter<string>;
set text(s: string) {
if (s === undefined) return;
let sOld = this.editor.getValue();
if (sOld === s) return;
this.editor.setValue(s);
this.editor.clearSelection();
this.editor.focus();
}
get text() {
return this.editor.getValue();
}
constructor(elementRef: ElementRef) {
var dir = this;
this.textChanged = new EventEmitter<string>();
let el = elementRef.nativeElement;
this.editor = ace.edit(el);
let session = this.editor.getSession();
session.setMode("ace/mode/xml");
session.setUseWrapMode(true);
this.editor.on("change", (e) => {
let s = dir.editor.getValue();
dir.textChanged.next(s);
});
}
}
エディター コンポーネント テンプレートには、次のようなディレクティブが含まれています。
<ace-editor id="editor" [text]="xml" (textChanged)="onXmlChanged($event)"></ace-editor>
とにかく、エディターのコンポーネント プロパティをプログラムで設定しようとすると、Angular が起動し、変更がプロパティを再度xml
設定するイベントを発行する ace エディターでイベントをトリガーするため、エンドレス ループが発生することに注意してください。xml
おそらく私が何か間違ったことをしているだけですが、現在、コードでこのハックを使用する必要があり、もちろん好きではありません:):
// ...
export class EditorComponent {
private _xml: string;
private _changeFrozenCount: number;
public set xml(s: string) {
this._xml = s;
}
public get xml() : string {
return this._xml;
}
constructor(private editorService: EditorService, private xmlService: XmlService) {
this._xml = "";
}
public onXmlChanged(xml: string) {
if (this._changeFrozenCount > 0) {
this._changeFrozenCount--;
return;
}
this._xml = xml;
}
public changeXml() {
this._changeFrozenCount = 1;
this._xml = "<sample>Hello</sample>"
}
}