使用可选参数和默认模型定义路由

define route with optional parameter and default model

本文关键字:默认 模型 定义 路由 参数      更新时间:2023-09-26

我想在 emberjs 中定义一个路由,它有一个可选参数例如:

/video/video/123

如果没有提供参数,我想使用默认模型/夹具。如果提供了参数,那么我想显然使用该参数查找模型。

如果我随后转到其他路由,并返回到没有参数的路由,则我想使用先前加载的模型。

例如:

startup app

/video - 显示我的默认/夹具模型

/video/123 - 显示模型 123

/another-route - 显示新路线

/video - 显示模型 123

这可能吗?

我最终使用了不同的解决方案:

  this.resource('video', function() {
    this.route('index', {path: '/'});
    this.route('item', {path: ':id'});
  });

这些路由支持:

/video - 显示我的默认/夹具模型

/video/123 - 显示模型 123

当用户访问/video时,VideoIndexRoute必须重定向到VideoItemRoute,没有任何id。

var VideoIndexRoute = Em.Route.extend({
  afterModel: function() {
    // this is the tricky part
    this.replaceWith('video.item', '');
  }
});

现在,VideoItemRoute 必须检查是否有任何关联的模型,当它丢失时,它应该使用默认夹具或新夹具。

var VideoItemRoute = Em.Route.extend({
  model: function(param) {
    if (param.id) {
      return this.store.find('video', param.id);
    }
  },
  setupController: function (controller, model) {
    if (!model) {
      model = this.store.createRecord('video',{
        name: 'default Name'
      });
      // or use fixture...
    }
    this._super(controller, model);
  }
});

有一种干净的方法可以做到这一点,尽管它有点"棘手"。这个想法是使用嵌套路由来保存 id,但不渲染它,而是让父路由负责使用渲染帮助程序渲染它。当你这样做时,所有的逻辑都可以存在于VideoChoiceController中,它将用于显示默认视频或特定视频。这样做时,无需显式"记住"最后一个视频,路由引擎表示的状态机会为您执行此操作。

App.Router.map(function) {
  this.resource('video', function(){
    this.route('choice', {path: ':video_id'});
  });
});
App.VideoRoute = Ember.Route.extend({
  model: function(params) {
    return App.get('defaultVideo');
  },
  setupController: function(controller, model) {
    var video_choice = this.controllerFor('video.choice')
    // this is necessary if you want, for example,
    // to display the name or a link to the default video
    // when a specific video is being displayed
    controller.set('model', model);
    if(Ember.isEmpty(video_choice.get('model'))){
      video_choice.set('model', model);
    }
  }
});
App.VideoChoiceRoute = Ember.Route.extend({
  model: function(params) {
    return this.get('store').find('video', params.video_id);
  },
  renderTemplate: function() {
    // if you don't override renderTemplate to do nothing, 
    // everything will still work but you will get an assertion
    // error that render should only be used once with a
    // singleton controller
  }
});

<script type="text/x-handlebars">
  <div>
    {{outlet}}
  </div>
</script>
<script type="text/x-handlebars" data-template-name='video'>
  <div> attrributes here always refer to the default video: {{name}} </div>
  {{render "video.choice"}}
</script>
<script type="text/x-handlebars" data-template-name='video'>
  <div> 
    attrributes here always refer to specific or last video, 
    or default if a specific video has never been loaded: {{name}}
  </div>
</script>

当然,你必须做一些有点时髦的事情,比如将最后一个视频存储在某个全局变量中,但这取决于你。

http://emberjs.jsbin.com/uhoQozu/1/edit

http://emberjs.jsbin.com/uhoQozu/1#/video

http://emberjs.jsbin.com/uhoQozu/1#/video/32

App.Router.map(function() {
  this.resource('videoModel', {path:'/video/:video_id'});
  this.resource('video');  // this resource can be accessed at /video
});