2013-10-08 6 views
2

У меня есть ProfilesController и ProfileController, который представляет собой один профиль.EmberJS - как получить доступ к родительскому контроллеру из дочернего контроллера?

// Profiles listing 
App.ProfilesController = Ember.ArrayController.extend({ 

}); 

// Single Profile representation 
App.ProfileController = Ember.ObjectController.extend({ 

    isActive: false, 

    actions: { 

     edit: function() { 

      // TODO: disable all profiles 
      // does not work ... parentController is undefined. pseudo code only! 
      this.get('parentController.children').forEach(function(profile) { 
       profile.set('isActive', false); 
      }); 

      // enable current profile 
      this.set('isActive', true); 
     } 
    } 
}); 

Обратите внимание, что это не полный код, эти 2 контроллеров имеют больше коды в моем приложении, и есть также ProfileView, что делает профиль листинга возможно.

Важной частью является то, как я могу получить доступ к родительскому профилю управления (ArrayController) изнутри ProfileController?

Я попытался (в действии редактирования):

this.get('parent') // => undefined 
this.get('parentController') // => null 
this.get('target') // => null 

Редактировать: Тем временем я пошел вниз по дереву объектов, и я пришел с невероятно Hacky, но рабочий раствор:

// disable all profiles 
this.get('controllers.profiles.target._activeViews.profiles.0._childViews.0._childViews').forEach(function(childView) { 
    childView.get('_childViews.0.controller').set('isActive', false); 
}); 

Он работает до тех пор, пока я не изменю что-то в структуре шаблонов, я полагаю. Там должен быть чист способом сделать это :-D

Edit 2: Для того, чтобы прояснить немного больше, вот моя Profiles шаблон, где profiles представляет собой набор профилей моделей (не Контроллеры Каждую модель представлена с помощью контроллера, так как я должен хранить состояние приложения, как текущий активный профиль и т.д.):

{{#each profile in profiles}} 
    {{view App.ProfileView profileBinding=profile}} 
{{/each}} 

и ProfileView

App.ProfileView = Ember.View.extend({ 

    templateName: 'profiles/profile', 

    init: function() { 
     this._super(); 
     var profile = this.get('profile'); 

     // Here I explicitely create a ProfileController instance, 
     // otherwise ProfilesController would be used instead of ProfileController 
     // because in EmberJS by default the View's controller is always the parent controller 
     this.set('controller', App.ProfileController.create()); 
     var controller = this.get('controller'); 
     controller.set('profile', profile);    
    } 
}); 

ответ

4

Вы можете установить itemController свойство в вашем each петли, так что вам не придется вручную создавать ProfileController с.

{{#each profile in profiles itemController="profile"}} 
    {{view App.ProfileView profileBinding=profile}} 
{{/each}} 

Затем вы можете использовать needs, чтобы убедиться, что ссылка на ProfilesController впрыскивают в каждую ProfileController. Вы должны использовать this.get('controllers.profiles') для доступа к самому ArrayController. Если вы делаете вещи The Ember Way, вы хотите получить доступ к свойству content этого контроллера (this.get('controllers.profiles.content')). Похоже, что вы не делаете это «Ужасный путь», а вместо этого собираете коллекцию с свойством profiles этого контроллера вместо свойства content. В этом случае вы должны использовать this.get('controllers.profiles.profiles'). Первый экземпляр profiles получает ProfilesController, второй экземпляр получает свойство profiles, которое установлено на этом контроллере.

App.ProfileController = Ember.ObjectController.extend({ 
    needs: ['profiles'], 
    actions: { 
     edit: function() { 

      this.get('controllers.profiles.profiles').forEach(function(profile) { 
       profile.set('isActive', false); 
      }); 

      // enable current profile 
      this.set('isActive', true); 
     } 
    } 
}); 
+0

Привет, Джереми, я пробовал это - проблема в том, что в моем случае controllers.profiles.profiles является RecordArray моих моделей, а не массивом контроллеров. – Alex

+0

controllers.profiles.content и controllers.profiles.model - пустой массив. Но я все это изменил до «ember way», и он намного чище (не создавая экземпляры контроллера вручную и т. Д.). – Alex

+0

Я не знаю, что можно захватить массив контроллеров, как вы надеетесь сделать. Вы можете переместить свойство 'active' в саму модель (как простое свойство, не нужно использовать' DS.attr'), а затем обновить модели напрямую. Я сделал это в приложении, и все работает отлично. –

1

вы хотите, чтобы сделать его скрытым (как и в любой дру er для использования супер) или достаточно назвать контроллеры, к которым вы хотите получить доступ явным?

Смотрите эту ссылку: http://eviltrout.com/2013/02/04/ember-pre-1-upgrade-notes.html

В вашем случае это будет:

App.ProfileController = Ember.ObjectController.extend({ 
    needs: ['profiles'], 
    actions: { 
     edit: function() { 

      this.get('controllers.profiles').forEach(function(profile) { 
       profile.set('isActive', false); 
      }); 

      // enable current profile 
      this.set('isActive', true); 
     } 
    } 
}); 
+0

К сожалению, this.get ('controllers.profiles'). Дети дают мне неопределенные.(«потребности» уже присутствовали в моем контроллере, так как мне это нужно для других вещей) – Alex

+0

Увы, вам больше не нужен параметр «children». this.get ('controllers.profiles'). ForEach (function (profile) {profile.set ('isActive', false);}); достаточно. Я изменил его и в своем ответе выше. –

+0

Это не вызывает ошибок, но не имеет никакого эффекта. Функция in forEach() даже не выполняется; -/ – Alex

Смежные вопросы