简体   繁体   English

ember.js - 使用可选参数和默认模型定义路径

[英]ember.js - define route with optional parameter and default model

I want to define a route in emberjs, that has an optional parameter eg: 我想在emberjs中定义一个路由,它有一个可选参数,例如:

/video and /video/123 /video/video/123

if no parameter is supplied, I want to use a default model/fixture. 如果没有提供参数,我想使用默认的模型/夹具。 if a parameter is supplied, then I want to obviously lookup the model using the parameter. 如果提供了参数,那么我想显然使用参数查找模型。

if I then go to a different route, and return to the route without the parameter, I want to use the previously loaded model. 如果我然后去不同的路线,并返回没有参数的路线,我想使用以前加载的模型。

eg: 例如:

startup app

/video - shows my default/fixture model /video - 显示我的默认/灯具模型

/video/123 - shows model 123 /video/123 - 显示模型123

/another-route - shows new route /another-route - 显示新路线

/video - shows model 123 /video - 显示模型123

is this possible? 这可能吗?

I ended up using a different solution: 我最终使用了不同的解决方案:

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

These routes support: 这些路线支持:

/video - shows my default/fixture model /video - 显示我的默认/灯具模型

/video/123 - shows model 123 /video/123 - 显示模型123

When the user access to /video , the VideoIndexRoute must redirect to VideoItemRoute without any id. 当用户访问/video ,VideoIndexRoute必须重定向到没有任何id的VideoItemRoute。

var VideoIndexRoute = Em.Route.extend({

  afterModel: function() {

    // this is the tricky part
    this.replaceWith('video.item', '');

  }

});

Now, the VideoItemRoute must check if there is any model associated, and when it is missing, it should use the default fixtures or a new one. 现在,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);

  }

});

There is a clean way to do this, although it is slightly "tricky". 有一种干净的方法可以做到这一点,虽然它有点“棘手”。 The idea is to use a nested route to hold the id, but not render it, instead having the parent route be responsible for rendering it using the render helper. 我们的想法是使用嵌套路由来保存id,但不渲染它,而是让父路由负责使用渲染助手来渲染它。 When you do it this way, all the logic can live in VideoChoiceController, and it will be used for displaying either the default video or a specific one. 当你这样做时,所有逻辑都可以存在于VideoChoiceController中,它将用于显示默认视频或特定视频。 When doing it this way, there is no need to explicitly "remember" the last video, the state machine that the route engine represents does it for you. 这样做的时候,没有必要明确地“记住”最后一个视频,路由引擎代表的状态机为你做了。

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>

Definitely, you'll have to do something a little funky, like storing the last video in some global variable, but that's up to you. 当然,你必须做一些有点时髦的事情,比如将最后一个视频存储在某个全局变量中,但这取决于你。

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

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

http://emberjs.jsbin.com/uhoQozu/1#/video/32 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
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM