何らかの形で尋ねる質問はたくさんあります。「ビューの一部がレンダリングされた後、どうすればよいですか?」(ここ、ここ、そしてここにいくつかあげるだけです)。答えは通常:
- ビューが最初にレンダリングされる
didInsertElement
ときにコードを実行するために使用します。 - 作成されたDOM要素にアクセスする必要がある場合は、ビューの変更がフラッシュされた後
Ember.run.next(...)
にコードを実行するために使用します。 - 必要なデータがロードされた後、オブザーバー
isLoaded
または同様のプロパティを使用して何かを実行します。
これについてイライラするのは、次のような非常に不器用な外観につながることです。
didInsertElement: function(){
content.on('didLoad', function(){
Ember.run.next(function(){
// now finally do my stuff
});
});
}
isLoaded
また、ember-dataを使用している場合は、すでにtrueである可能性があるため、必ずしも機能するとは限りません(レコードが以前にロードされており、サーバーから再度要求されていない場合)。したがって、シーケンスを正しく行うことは困難です。
その上、おそらくすでに次のようにビューテンプレートでisLoadedを監視しています。
{{#if content.isLoaded}}
<input type="text" id="myTypeahead" data-provide="typeahead">
{{else}}
<div>Loading data...</div>
{{/if}}
コントローラーでもう一度実行すると、重複しているように見えます。
私は少し斬新な解決策を思いつきましたが、それは作業が必要であるか、実際には悪い考えです...どちらの場合も当てはまる可能性があります。
含まれているハンドルバーテンプレートが実行されると、カスタム名でイベントを発生させるという小さなハンドルバーヘルパー{{fire}}
を作成しました(つまり、サブビューが再レンダリングされるたびに実行する必要がありますよね?)。
これが私の非常に初期の試みです:
Ember.Handlebars.registerHelper('fire', function (evtName, options) {
if (typeof this[evtName] == 'function') {
var context = this;
Ember.run.next(function () {
context[evtName].apply(context, options);
});
}
});
これは次のように使用されます:
{{#if content.isLoaded}}
{{fire typeaheadHostDidRender}}
<input type="text" id="myTypeahead" data-provide="typeahead">
{{else}}
<div>Loading data...</div>
{{/if}}
これは基本的にそのまま機能しますが、私がすでに知っているいくつかの欠陥があります。
- コントローラのメソッドを呼び出します...代わりに、少なくとも「イベント」を祖先ビューオブジェクトに送信できるようにする方が、おそらくデフォルトの動作にする方がよいでしょう。試し
{{fire typeaheadHostDidRender target="view"}}
ましたが、うまくいきませんでした。ヘルパーに渡されたものから「現在の」ビューを取得する方法はまだわかりませんが、明らかに{{view}}
ヘルパーはそれを行うことができます。 - ここでやっていることよりも、カスタムイベントをトリガーするより正式な方法があると思いますが、まだそれを学びませんでした。jQuery
.trigger()
は、ビューでは機能する可能性がありますが、コントローラーオブジェクトでは機能しないようです。これを行うための「燃えさし」の方法はありますか? - このイベントがトリガーされたが、ビューが実際にはDOMに追加されなかった場合など、私にはわからないことがあるかもしれません...?
ご想像のとおり、私はBootstrapのTypeaheadコントロールを使用しており、<input>
レンダリング後にワイヤリングする必要があります。これは、実際には、テンプレートでいくつかのネストされた{{#if}}
ブロックがtrueと評価された後にのみ発生します。私もjqPlotを使用しているので、このパターンの必要性に何度も遭遇します。これは実行可能で便利なツールのように見えますが、このアプローチを馬鹿にするような全体像が欠けている可能性があります。または、検索に表示されていない別の方法がありますか?
誰かが私のためにこのアプローチを改善するか、それが悪い考えである理由を教えてもらえますか?
アップデート
私はいくつかのビットを理解しました:
- 私は最初の「本物の」含有ビューを
options.data.view.get('parentView')
...おそらく明らかなもので得ることができますが、それがそれほど単純であるとは思いませんでした。 obj.trigger(evtName)
実際には、任意のオブジェクトに対してjQueryスタイルを実行できます...ただし、オブジェクトはEmber.Evented
ミックスインを拡張する必要があります。そのため、Emberでこの種のイベント送信を行う正しい方法だと思います。目的のターゲットが拡張されていることを確認しEmber.Evented
てください(ビューはすでに拡張されています)。
これまでに改善されたバージョンは次のとおりです。
Ember.Handlebars.registerHelper('fire', function (evtName, options) {
var view = options.data.view;
if (view.get('parentView')) view = view.get('parentView');
var context = this;
var target = null;
if (typeof view[evtName] == 'function') {
target = view;
} else if (typeof context[evtName] == 'function') {
target = context;
} else if (view.get('controller') && typeof view.get('controller')[evtName] == 'function') {
target = view.get('controller');
}
if (target) {
Ember.run.next(function () {
target.trigger(evtName);
});
}
});
今私が見逃しているのは、目的のターゲットを渡す方法を理解することだけです(たとえば、コントローラーやビュー-上記のコードは推測しようとします)。または、全体の概念を破る予期しない動作があるかどうかを把握します。
他の入力はありますか?