4

現在、ルートを次のように定義しています。

App.Router.map(function() {
    this.resource('players', { path: ':page_id' }, function() {
        this.resource('player', { path: ':player_id' });
    });
});

アイデアは、左側にプレイヤー名のリストがあるということです。表示されるプレイヤー名は、page_id によって異なります。右側には、player_id に基づいて 1 人のプレーヤーとそのすべての情報が表示されます。問題は、どちらも独立していることです。つまり、リストの最初のプレーヤーを表示しているときに、3 番目のプレーヤー ページにいることも、プレーヤーがまったく表示されないこともあります。

これは、次のプレーヤー ページに移動するためにクリックしたときに呼び出される PlayersController のメソッドです。

doTransition: function() {
    var players = App.Player.findAllForPage(this.playersPerPage, this.currentOffset);
    players.reopen({
        id: this.currentOffset
    });
    var playerController = this.get('controllers.player');
    var currentPlayer = playerController.getWithDefault('content');
    if (currentPlayer) {
        this.transitionToRoute('player', players, currentPlayer);
    } else {
        this.transitionToRoute('players', players);
    }    
}

私がやろうとしていること:クリックして次のプレーヤーページに移動すると、現在表示されているプレーヤーがない場合は PlayersRoute に遷移し、そうでない場合は PlayerRoute に遷移して、遷移が完了したときにプレーヤーがまだ表示されるようにします。

問題: 現在表示されているプレーヤーがなくても、currentPlayer 変数が常に null ではない場合があります。おそらくどこかから現在のルートを取得することで、これを回避する方法はありますか?

4

2 に答える 2

5

2 つのセクション ( に基づくプレーヤーのリストpage_id、および に基づくプレーヤー情報player_id) が完全に独立していると考えると、ルートをネストせず、代わりに 2 つの名前付きアウトレット (それらleftを およびright、またはpageなどplayer) に選択的にレンダリングします。

ルーター:

App.Router.map(function() {
    this.resource('page', { path: ':page_id' });
    this.resource('player', { path: ':player_id' });
 });

アプリケーション.hbs:

{{outlet page}}
{{outlet player}}

そして、ルートを適切なテンプレートにレンダリングするrenderTemplateためにオーバーライドできます。明確にするために、ルートはプレイヤールートとして現在持っているものを表示し(page_idに依存しますが、ページには多くのプレイヤーがいるため、ルートはページに基づいてプレイヤーを表示します)、ルートはに基づいてプレイヤー情報を表示します.pageplayerpageplayerplayer_id

(ちなみに、現在の方法でリソースを入れ子にすることはできないと思います。入れ子resource playerresource playersすることができるのはルートだけだと思います。)

編集:複数の動的セグメントで単一のルートを使用する

あなたの提案はうまくいくと思います。リンクされた例から、「親」リソース (ネストされたルートではなく、/page/ や /page/:page_id/player/:player_id などのより一般的なパスを持つ) を作成する必要があるようです。model次に、適切なルートでモデルを個別にセットアップしserialize、ダブル ダイナミック セグメント ルートにフックを提供するだけです。

serialize: function(model) {
    return {
        page_id : this.modelFor('page').get('id') 
        player_id : this.modelFor('player').get('id')
    };
}

modelページ パネルとプレーヤー パネルを完全に独立させることができると述べたので、渡されたオブジェクトに依存していないことに注意してくださいmodelFor。代わりに使用します。

redirectここでフックを介して何も提案されていない場合は、レンダリングするデフォルトのページ/レンダリングするデフォルトのプレーヤーに関するロジックも処理できると思います。

最後に、renderTemplatePagePlayer ルートでオーバーライドして、実際にレンダリングを行います。

renderTemplate: function(model, controller) {
  this.render("page", { into: "page" });
  this.render("player", { into: "player"});
}

/page/1/player/2 から /page/1/player/3 に移動すると、ページ ルートが再入力されないため、より一般的なルートでテンプレートをレンダリングしないように注意する必要があると思います.

于 2013-05-23T04:38:58.860 に答える
4

Sherwin の答えは、私がどこに行くのかについての良い考えを与えてくれましたが、完全な例を挙げて、最終的に実装したものの一般的な考えを示したかっただけです。これは、将来の参照に役立つ可能性があります。

モデルを単純な int にすることで簡単にします。これにより、URL からモデルへ、またはその逆に直接変換できます。

テンプレート:

<script type="text/x-handlebars">
  {{outlet a}}
  {{outlet b}}
</script>

<script type="text/x-handlebars" id="a">
  {{model}}
</script>

<script type="text/x-handlebars" id="b">
  {{model}}
</script>

応用:

App = Ember.Application.create();

App.Router.map(function() {
  // This route has 2 dynamic segments
  this.resource("ab", { path: "/:a/:b" });
});

App.IndexRoute = Ember.Route.extend({
  redirect: function() {
    // At the entry point, encapsulate the 2 models in the context object,
    // and transition to the route with dual dynamic segments
    this.transitionTo('ab', {a: 3, b:4});
  }
});

App.AbRoute = Ember.Route.extend({
  model: function(params) {
    // The model is {a, b} directly
    return params;
  },

  renderTemplate: function(){
    // Render in the named outlet using the right controller
    this.render('a', {into: 'application', outlet: 'a', controller: 'a'});
    this.render('b', {into: 'application', outlet: 'b', controller: 'b'});
  },

  serialize: function(model) {
    return {
      a: model.a,
      b: model.b
    };
  },

  setupController: function(controller, model) {
    // Setup each controller with its own model
    this.controllerFor('a').set('model', model.a);
    this.controllerFor('b').set('model', model.b);
  }
});

追記:

単一の 'ab' テンプレート レンダリング{{model.a}}{{model.b}}AbController を使用することも可能でしたが、別のコントローラーとテンプレートを使用する方がクリーンであり、再利用が可能になると思いました。さらに、コントローラーの 1 つが ArrayController である可能性があり、完全に正常に動作します。

例のJS Bin

于 2013-07-22T15:09:50.370 に答える