Как правильно получить доступ к параметрам из Ember.Route. Контроллер настройки?

Ember.Route.model имеет доступ к переменной params, а Ember.Route.setupController — нет. Для меня это проблематично, потому что мой путь состоит из нескольких динамических сегментов, и мне нужно использовать их все в моем шаблоне.

Конкретно мой путь выглядит так: /project/:project_id/task/:task_id. Обратите внимание, что задача может принадлежать многим проектам, а не только одному. Поэтому мы не можем сказать, какой проект мы рассматриваем, просто взглянув на саму задачу: мы должны использовать идентификатор проекта, найденный в URL-адресе. Вот как я это делаю сейчас:

App.TaskRoute = Ember.Route.extend({

  // This works just fine:
  serialize: function(model) {
    return {
      task_id: model.get('id'),
      project_id: this.modelFor('project').get('id')
    };
  },

  model: function(params) {
    this.set('parentProjectId', params.project_id);

    return App.Task.find(params.task_id);
  },

  setupController: function(controller, model) {
    var parentProject = this.modelFor('project') ?
                        this.modelFor('project') :
                        App.Project.find(this.get('parentProjectId'));
    controller.set('parentProject', parentProject);

    controller.set('content', model);
  }
});

Может быть, я параноик, это просто кажется хакерским. Если бы маршрут должен был иметь доступ к параметрам, то к нему уже было бы прикреплено свойство params. Есть ли способ лучше?

РЕДАКТИРОВАТЬ: я сделал некоторые обновления кода выше. Кроме того, мои маршруты выглядят так:

App.Router.map(function() {
  this.resource('project', { path: '/project/:project_id' });
  this.resource('task', { path: 'project/:project_id/task/:task_id' });
});

person NudeCanalTroll    schedule 19.03.2013    source источник


Ответы (2)


У вас нет доступа к этим параметрам в хуке setupController. Крючок модели имеет доступ к объекту params, потому что он вызывается только при входе в ваше приложение через URL-адрес.

Ваш код выглядит довольно хорошо, если вы действительно знаете, что хотите сделать это таким образом. Что кажется вам хакерским в этом? Глядя на этот код, я спрашиваю себя, почему вы не разделили логику своего маршрута на ProjectRoute и подчиненный TaskRoute. Разве это не сработает для вас?

Обновление: ответ на ваши изменения

Вложение ресурсов, вероятно, является ключом к успеху в вашем случае:

App.Router.map(function() {
  this.resource('project', { path: '/project/:project_id' }, function(){
    this.resource('task', { path: '/task/:task_id' });
  });
});

Поскольку TaskRoute не является вложенным, вам нужно переименовать его в ProjectTaskRoute:

App.ProjectTaskRoute = Ember.Route.extend({
...
});

Это должно позволить вам удалить parentProjectId property из маршрута.

person mavilein    schedule 19.03.2013
comment
Ах, я не знал, что метод модели вызывается только при первой загрузке, но это объясняет многие странности, которые я видел. Например, мой код выше не работает, если я открываю /project/1/tasks/2 напрямую, потому что model не вызывается, поэтому атрибут parentProjectId не установлен. В этом случае я должен сделать var parentProject = this.modelFor('project') внутри setupController. У меня есть отдельный ProjectRoute. Открытие /project/1 покажет задачи для проекта. Щелкнув по задаче, вы откроете /project/1/tasks/1. Представлению задачи нужна обратная ссылка на проект, поэтому я вытаскиваю проект из URL-адреса. - person NudeCanalTroll; 20.03.2013
comment
Так теперь работает? Моя идея заключалась в том, чтобы также использовать this.modelFor(project). Когда вы входите в свое приложение через /project/1/tasks/2, ProjectRoute должен быть затронут первым, а его хук модели. После этого вы можете использовать modelFor для доступа к нему. Кажется немного избыточным устанавливать parentProject в вашем контроллере, когда вы используете ember-data для моделирования своих данных. Это свойство не должно существовать в вашей модели задач? - person mavilein; 20.03.2013
comment
Задача может принадлежать нескольким проектам (подумайте о проектах как о тегах), поэтому вместо того, чтобы иметь ассоциацию «принадлежит к проекту», она имеет ассоциацию «много проектов». Таким образом, я не могу сказать, в каком проекте я нахожусь (и, следовательно, куда должна ссылаться кнопка «Назад»), просто взглянув на задачу. Я должен проверить URL. Во всяком случае, я попробую модель для вещи. Я думаю, что мои маршруты настроены неправильно, поэтому при переходе к /project/1/task/2 сначала запускается TaskRoute. Я думаю, мне нужно вложить маршруты задач в маршруты проектов? Я обновлю свой вопрос, чтобы показать, как выглядят мои маршруты. - person NudeCanalTroll; 20.03.2013
comment
Да, ваши маршруты обязательно должны быть вложенными! Тогда ProjectRoute будет поражен первым. Я прокомментирую ваше обновление, когда у меня будет время. - person mavilein; 20.03.2013