グラフ コンポーネントを作成し、次のいずれかが発生したときにレンダリングするようにします。
- その
data
性質が変化する - DOMに挿入されます
問題は、これらのイベントが両方とも発生すると、チャートが 2 回レンダリングされることです。
コンポーネントは次のとおりです。
App.BarChartComponent = Ember.Component.extend({
classNames: ['chart'],
chart: BarChart().margin({left: 40, top: 40, bottom: 80, right: 40}),
didInsertElement: function() {
Ember.run.once(this, 'update');
},
update: function() {
if (this.get('isLoaded')) {
d3.select(this.$()[0])
.data([ this.get('data') ])
.call(this.get('chart'));
}
}.observes('data')
});
私はこのように使用しています(会社のテンプレート内でレンダリングされています)
{{bar-chart data=controller.controllers.companies.data
isLoaded=controller.controllers.companies.model.isLoaded}}
コントローラーは次のようになります (ルートを変更するとCompaniesController
モデルが更新されます)。
App.CompaniesController = Ember.ArrayController.extend({
data: function() {
if (!this.get('model.isLoaded')) {return;}
var data = this.map(function(company) {
return {
category: company.get('name'),
count: company.get('newContracts'),
};
});
return data;
}.property('model')
});
今は jsfiddle を作成する時間がありませんが、1 つのケースを除いてすべてが期待どおりに機能します:index
ルートで開始し、モデルをロードしてからルートに戻る場合index
です。この時点で、前のルート (会社 A、B、および C) のデータが読み込まれますが、index
ルート上にいるため、コンポーネントはレンダリングされません。ここで、新しいルート (会社 D、E、F など)をクリックすると、次のようになります (私の知る限り):
- 約束が解決し、新しい会社がロードされるまで何も起こりません
- それらが読み込まれるとすぐに、
companies
テンプレートがレンダリングされます。didInsertElement
これは私のコンポーネントでトリガーされ、update
関数を実行します。 - myの
data
計算されたプロパティがCompaniesController
再度計算され、その change イベントが発生します。 - 私のコンポーネントの
update
メソッドは、変更を監視し、data
それ自体を再レンダリングします。
そのため、チャートは 2 回レンダリングされます。1 回は古いデータで、もう 1 回は新しいデータでレンダリングされます。瞬間的であれば問題ないかもしれませんが、滑らかなアニメーションなので目立ちます。
を使用Ember.run.once
するとこれを防ぐことができると思いましたが、そうではないと思います-または、間違って使用しています。モデルがロードされているかどうかだけでなく、コントローラーがコンテンツのスワップアウトを完了したかどうかを確認する必要があるようです。どんなアイデアでも大歓迎です!