Ember.js: Как обновить шаблоны родительских маршрутов в сценарии вложенных маршрутов?

Мой макет страницы (шаблон приложения) выглядит так (упрощенно):

Ember page layout

Я использую его для разных маршрутов (список предложений + предложение, список клиентов + детали клиента). Списки отображаются в выводе для суб-навигации.

Мой код маршрутизатора:

App.Router.map(function () {
    //...
    this.resource('offers', function () {
        this.resource('offer', { path: '/:offer_id' });
    });
}

Мои маршруты:

App.OffersRoute = Ember.Route.extend({
   model: function () {
       return App.Offer.find();
   },
   renderTemplate: function (controller, model) {
       this.render('offer-list', { 
           into: 'application', outlet: 'sub-navigation', controller: 'offers' });
       this.render('offer-list-title', { into: 'application', outlet: 'page-title' });
       this.render('offer-list-content', { into: 'application' });
   }
});

App.OfferRoute = Ember.Route.extend({
   model: function (params) {
      return App.Offer.find(params.offer_id);
   },
   renderTemplate: function () {
      this.render('offer-title', { into: 'application', outlet: 'page-title' });
      this.render('offer-content', { into: 'application' });
   }
});

Теперь это работает до сих пор.

http://.../#/offers

показывает список и заголовок "Резюме предложения" и статический html-контент. Я нажимаю на одно из предложений в списке, перейдя в

http://.../#/offers/23

все в порядке: он по-прежнему показывает список предложений в области суб-навигации и правильный заголовок и содержание предложения.

Теперь моя проблема:

Если я вернусь к

http://.../#/offers

(с помощью помощника #linkTo в меню), тогда область {{outlet}}/content становится пустой (а не статический html от ранее), а заголовок по-прежнему является заголовком в {{page-title}} предложения /23 маршрута.

Как я могу позволить моему приложению "повторно отобразить" шаблон, как определено в OfferRoute renderTemplate()?

P.S.: Я использую Ember.js 1.0.0-RC.3

Ответ 1

Использование встроенных маршрутов Index и поддержка иерархии ApplicationRouteOffersRouteOfferRoute решит вашу проблему.

Если вы включите ведение журнала перехода маршрутизатора, вы увидите, что при навигации по Offers вы фактически вводите маршрут Offers.Index:

App = Ember.Application.create({
  LOG_TRANSITIONS: true
});

Это означает, что вы можете установить свой статический заголовок Предложения и установить статический контент предложений в OffersIndexRoute, и он будет правильно установлен в первый раз и снова настроен, если вы вернетесь к нему изнутри страницы подробной информации о предложениях. Чтобы это сработало, вы также должны сохранить иерархию ApplicationRouteOffersOffer {{outlet}}, не превращая все непосредственно в ApplicationRoute {{outlet}}. Причина, по которой вы должны сохранить эту иерархию, заключается в том, что, создав дочерний элемент (Offer template) непосредственно в шаблон Application, вы удалите шаблон Offers, и когда вы попытаетесь вернуться к OffersRoute, его шаблон был удален и он ничего не показывает.

Маршрут указателя

Используйте OffersIndexRoute для заполнения ApplicationRoute {{outlet}} и {{outlet page-title}}.

JS:

//this renders the title and the main content for Offers
App.OffersIndexRoute = Ember.Route.extend({
  renderTemplate: function (controller, model) {
    this.render('offer-list-title', { into: 'application', outlet: 'page-title' });
    this.render();
  }
});

App.OffersRoute = Ember.Route.extend({
   model: function () {
       return App.Offer.find();
   },
   renderTemplate: function (controller, model) {
     this.render('offer-list', { 
         into: 'application', outlet: 'sub-navigation', controller: 'offers' });

     // render this in OffersIndexRoute instead
     //this.render('offer-list-title', { into: 'application', outlet: 'page-title' });

     this.render('offer-list-content', { into: 'application' });
   }
});

Рули:

<script type="text/x-handlebars" data-template-name="offer-list-content">
  {{outlet}}
</script>

<script type="text/x-handlebars" data-template-name="offers/index">
  Offers content
</script>  

Выход в offers-list-content будет заполнен шаблоном OffersIndexRoute или шаблоном Offer, в зависимости от текущего маршрута.

Поддержание иерархии {{outlet}}

Разрешить OfferRoute отображать шаблон содержимого в шаблон OffersRoute, а не форсировать его в ApplicationRoute.

App.OfferRoute = Ember.Route.extend({
   model: function (params) {
      return App.Offer.find(params.offer_id);
   },
   renderTemplate: function () {
     this.render('offer-title', { into: 'application', outlet: 'page-title' });

     // preserve the hierarchy and render into the Offers {{outlet}}, which is the default
     //this.render('offer-content', { into: 'application' });
     this.render('offer-content');
   }
});

Рабочий пример JSBin