Ember Modal可以从任何地方进入

时间:2015-05-20 17:42:49

标签: javascript ember.js modal-dialog ember-router

我正在构建一个具有用户设置面板的应用程序,该面板会在模式对话框中弹出。该面板应该可以从应用程序的任何页面访问。我正试图找出在Ember中构建它的最佳方法。

我想以这样的方式构建它:当app重定向到“/ settings”路径时,模式对话框会在背景中显示当前路径,如您所料。然后当模态关闭时,app会重定向回该路径。

如果用户从她的浏览器直接进入“/ settings”,则模式将在后台显示默认页面。

这是我到目前为止所做的:

export default Ember.Route.extend({

  defaultParentRoute: "project.index",

  beforeModel: function(transition){
    // get the name of the current route or if
    // user came directly to this url, use default route name
    var parent = this.get("defaultParentRoute");
    var application = this.controllerFor('application');
    if(application && application.get('currentRouteName')) {
      parent = application.get('currentRouteName');
    }
    this.set("parentRoute", parent);
  },

  renderTemplate: function(){
    // make sure the current route is still rendered in the main outlet
    this.render(this.get("parentRoute"));

    // render this route into the 'modal' outlet
    this.render({
      into: 'application',
      outlet: 'modal'
    });
  },  

  actions: {
    removeModal: function(page){ 
      // go back to the previous route     
      this.transitionTo(this.get("parentRoute"));
    }
  }

});

从应用程序中的链接导航到路径时,这非常有效。但是,如果用户在浏览器中直接进入“myapp / settings”,则会呈现默认页面模板但没有任何数据,或者它尝试使用我的设置路径中的“模型”数据。

如何确保模态下的模板使用适当的数据进行渲染?

Here's a JS Bin to demonstrate。尝试点击应用中任意页面的“设置”,然后在设置模式打开时刷新浏览器。

1 个答案:

答案 0 :(得分:1)

鉴于Ember的惯例,这个组织似乎有点不自然。通常,URL应该表示足以重建用户所在位置的状态的序列化版本(see this old discussion)。

似乎您想将模态状态和当前路由放入URL中。设置模式面板可以更自然地从其他路径访问,但不更改URL,然后有另一个专用于设置的单独路由,仅显示设置。

模态面板看起来更像是一个下拉菜单,其打开和关闭不会更改URL,即使它们代表一个次要的状态更改。

如果您希望在URL中反映设置模式的原因是人们可以将其添加为书签或共享链接,则可以选择在设置页面上设置永久链接以将其转到其他专用路径这是可以分享的。

没有将设置作为路由的棘手的一点是,没有明显的地方可以加载模型,其行为与路径的model挂钩一样好用或者很容易(即等待直到承诺决定完成过渡)。

解决此问题的一种方法是在设置服务中加载设置模型的功能,可以在任何地方注入:

SomeController = Ember.Controller.extend({
  settings: Ember.inject.service()
});

并且设置服务仅在模型加载后显示。

SettingsService = Ember.Service.extend({
  settingsLoaded: false,
  ensureLoaded: function() {
    var _this = this;
    return new Ember.RSVP.Promise (resolve) {
      if (_this.get('settingsLoaded')) {
        resolve()
      } else {
        _this.store.find('settings', someId).then(function(model) {
          _this.set('model', model);
          _this.set('settingsLoaded', true);
          resolve();
        });
      }
    };
  }
});

最后,您可以在某个想要显示设置模式的控制器上有一个功能,只有在加载设置后才显示它:

showSettings: function() {
  this.get('settings').ensureLoaded().then(function() {
    ... # something to show the modal pane.
  });
}