0

3 つの状態を持つ Ember ビューを作成しようとしています。具体的には、「送信」から「保存中...」、「完了!」に遷移する送信ボタンです。この目標を達成するには多くの方法がありますが、くだらないコードを書かずにこれを達成するための「ベスト プラクティス」は、Ember の観点からはどうなるのだろうと考えていました。

現在、次のコードがあります。

UiControls.SubmitButton = Ember.View.extend({

  template: function() {  
    var template = '{{#if view.isNotStarted}}Submit{{/if}}';
    template += '{{#if view.isStarted}} <i class="icon-spinner icon-spin"></i>Saving...{{/if}}';
    template += '{{#if view.isFinished}} <i class="icon-check-sign"></i>Finished!{{/if}}'
    return Ember.Handlebars.compile(template);
  }.property(),

  isNotStarted: true,
  isStarted: null,
  isFinished: null,

  classNames: ['btn', 'btn-green'],

  isDisabled: false,

  click: function(){
    if (!this.get('disabled')){
      this.set('isNotStarted', false);
      this.set('isStarted', true);
      this.set('isFinished', false);
      this.timer();
    }
  },

  /* Simulates a server call */
  timer: function(){
    (function(self){
      setTimeout(function(){
        self.set('isStarted', false);
        self.set('isFinished', true);
      }, 500);
    })(this);
  }
});

私にとってこれは本当に醜いです。ハンドルバーの意図的に制限された条件付き構文を操作するために、イベントに基づいて個々のブール値を設定しています。

私が欲しいのは、Ember StateManager プロパティのようなものを受け入れるハンドルバー構造です (Handlebars 構文では不可能です)。または、少なくとも、StateManager から計算されたプロパティに基づいてテンプレートを変更したいと考えています (これも不可能です)。だから私の質問は、コードの重複を防ぐために上記のコードを記述して、多くの小さなブールフラグ操作を介して手動で状態遷移を処理するより良い方法はありますか?

4

1 に答える 1

2

私にとってこれは本当に醜いです。ハンドルバーの意図的に制限された条件構文を操作するために、イベントに基づいて個々のブール値を設定しています。

完全に同意します。これは、リファクタリングが必要であることを示しています。

私が欲しいのは、Ember StateManager プロパティのようなものを受け入れるハンドルバー構造です (Handlebars 構文では不可能です)。

カスタム ハンドルバー ヘルパーを作成すれば可能ですが、正直なところ、その方法はお勧めしません。

または、少なくとも、StateManager から計算されたプロパティに基づいてテンプレートを変更したい (繰り返しますが、不可能です)。

なぜだめですか?そのプロパティを持っていたとしても、すべてのブール値なしでテンプレートを変更することはできません。

だから私の質問は、コードの重複を防ぐために上記のコードを記述して、多くの小さなブールフラグ操作を介して手動で状態遷移を処理するより良い方法はありますか?

はい。ハンドルバーにこの制限がある理由は、複雑さとロジックがテンプレートの一部になるのを防ぐためです。たとえば、ある値に基づいて 1-of-3 バージョンのように表示する必要があるときはいつでも。そのようなロジックは、ビューまたはコントローラー レイヤーに属します。

あなたの例を見ると、変更する必要があるテンプレートの2つの側面があります

  • text : "Submit"、"Saving..."、または "Finished!" のいずれかである必要があります。
  • iconClassNames : 空、「icon-spinner icon-spin」または「icon-check-sign」のいずれか

これを念頭に置いて、テンプレートを次のように単純化できます。

<i {{bindAttr class="view.iconClassNames"></i>{{view.text}}

プロパティをビューに追加します

UiControls.SubmitButton = Ember.View.extend({
  template: Ember.Handlebars.compile('<i {{bindAttr class="view.iconClassNames"></i>{{view.text}}'),
  classNames: ['btn', 'btn-green'],
  isDisabled: false,
  text: "Submitted",
  iconClassNames: "",
  click: function(){
    if (!this.get('disabled')){
      this.set('text', 'Saving...');
      this.set('iconClassNames', 'icon-spinner icon-spin');
      this.timer();
    }
  },

  /* Simulates a server call */
  timer: function(){
    (function(self){
      setTimeout(function(){
      this.set('text', 'Finished!');
      this.set('iconClassNames', 'icon-check-sign');
      }, 500);
    })(this);
  }
});

これはシミュレーションでは機能しますが、理想的ではありません。本当に、text と iconClassNames を stateManager にする必要boundがあります。textこれは、およびiconClassNames計算されるプロパティを変更することを意味します。理想的には、モデル オブジェクトの基礎となる状態に基づいて計算click()され、コントローラーで定義されますが、シミュレーションの場合は次のようになります。

UiControls.SubmitButton = Ember.View.extend({
  template: Ember.Handlebars.compile('<i {{bindAttr class="view.iconClassNames"></i>{{view.text}}'),
  classNames: ['btn', 'btn-green'],
  isDisabled: false,
  state: 'new',
  text: function() {
    //return appropriate button text based on state
  }.property('state'),
  iconClassNames: function() {
    //calculate text based on state
  }.property('state'),

  /* Simulates a server call */
  click: function(){
    if (!this.get('disabled')){
      this.set('state', 'saving');
      this.timer();
    }
  },

  /* Simulates a server call */
  timer: function(){
    (function(self){
      setTimeout(function(){
        self.set('state', 'finished');
      }, 500);
    })(this);
  }
});
于 2013-06-11T21:21:27.723 に答える