【问题标题】:Emberjs Modal as a routeEmberjs 模态作为路线
【发布时间】:2015-01-14 12:24:02
【问题描述】:

我试图弄清楚如何将路线转换为模式,以便您可以通过任何其他路线导航到它,同时保留底层(以前的)模板。

例如:

http://example.com/site/index 转到 index.hbs

http://example.com/site/page2 转到 page2.hbs

http://example.com/site/article/1234 如果用户来自另一个域,则转到 article.hbs(重新开始)

但是如果用户来到任何其他路线,http://example.com/site/article/1234 在“article-modal”出口内打开 article.hbs。

这里是 router.js

Market.Router.map(function() {
this.route('index', { path: '/' });
this.route('start', { path: 'start' });
this.route('article', { path: 'article/:article_id' });
this.route('404', { path: '*:' });
});

这里是 application.hbs

<div class="main-container">{{outlet}}</div>
{{outlet "article-modal"}}

这里是 article.js 路由 另一种情况 #1

Em.Route.extend({
beforeModel: function(transition, queryParams) {
    if(!Em.isEmpty(this.controllerFor('application').get('currentRouteName'))) {
        this.render('article', {
    into: 'application',
    outlet: 'article-modal'
  });
        return Em.RSVP.reject('ARTICLE-MODAL');
    }
},

model: function(params) {
    return this.store.find('article', params.id);
},

actions: {
error: function(reason) {
        if(Em.isEqual(reason, 'ARTICLE-MODAL')) { // ARTICLE-MODAL errors are acceptable/consumed
            //
            return false;
        }
        return true;
}
}
});

这里是 article.js 路由 另一种情况 #2

Em.Route.extend({

renderTemplate: function() {
    if(!Em.isEmpty(this.controllerFor('application').get('currentRouteName'))) {
        this.render({into: 'index', outlet: 'article-modal'});
    } else {
        this.render({into: 'application'});
    }

},

model: function(params) {
    return this.store.find('product', params.id);
},
});

案例#1 的问题是浏览器地址栏不反映当前路由。如果用户从索引路由转到文章路由,浏览器地址栏仍会显示 /index.. 所以如果他按下返回按钮应用程序会中断。

案例 #2 的问题是它丢弃了 index.hbs 的内容,因为文章路由没有嵌套。

Ember 甚至可以拥有这样的功能吗?

谢谢:)

【问题讨论】:

    标签: ember.js ember-router


    【解决方案1】:

    这是我对这个问题的第二个回答。我的原始答案 (https://stackoverflow.com/a/27947475/1010074) 没有直接回答 OP 的问题,但是,我在该答案中概述了在 Ember 中处理模态的其他三种方法,并将其留在那里以防对其他人有帮助。

    解决方法:定义多条路径相同的路径

    虽然 Ember 通常不允许您定义使用相同路径的两条路由,但实际上您可以使用相同的有效路径来定义嵌套路由和非嵌套路由,并且 Ember 可以很好地使用它。从我原来的答案中选择 3,我已经整理了一个我认为对你有用的概念证明。这是一个 JS Fiddle:http://jsfiddle.net/6Evrq/320/

    基本上,您可以拥有一个看起来像这样的路由器:

    App.Router.map(function () {
        this. resource("index", {path: "/"}, function(){ 
            this.route("articleModal", {path: "/article"});    
        });
        this.route("article", {path: "/article"});
    });
    

    在您的模板中,链接到index.articleModal 路由:

    {{#link-to "index.articleModal"}}View article!{{/link-to}}
    

    由于articleModalindex 内部呈现,因此您的index 路由不会未呈现。由于 URL 路径更改为 /article,因此重新加载页面会将您路由到您的常规 Article 路由。

    免责声明:我不确定这是否是利用当前 Ember 中的错误,所以这里的里程可能会有所不同。

    【讨论】:

    • 里程该死,这就是答案! :) 坦率地说,这甚至从未在我的脑海中出现过。我认为这表明 Ember 框架中最薄弱的“组件”仍然是路由器!希望在 2.0 之后,他们将取消所有车把脚本标签,他们可能会像这样专注于 smt。 +1
    • 有谁知道这种方法今天仍然有效吗?如果有,使用的是什么版本的 Ember?
    【解决方案2】:

    编辑:刚刚重新阅读 OP 的问题并意识到我不理解他的问题,所以我创建了一个新答案 (https://stackoverflow.com/a/27948611/1010074),概述了我在尝试某些东西后想出的另一种方法。

    选项 1:Ember 建议的模态处理方法

    Ember 网站有一本关于他们如何推荐处理模式对话框的“食谱”: http://emberjs.com/guides/cookbook/user_interface_and_interaction/using_modal_dialogs/

    基本上,您将在打开模式的路线中创建一个操作:

    App.ApplicationRoute = Ember.Route.extend({
      actions: {
        openArticleModal: function(article) {
          return this.render(article, {
            into: 'application',
            outlet: 'modal',
            controller: this.controllerFor("article")
          });
        }
      }
    });
    

    然后从您的控制器/另一个路由调用this.send("openArticleModal", article),或者您可以在模板中执行类似&lt;button {{action "openArticleModal" article}}&gt;View Artice&lt;/button&gt; 的操作。

    本质上,此方法使模态脱离路由状态,这意味着模态不会被 URL 绑定,但是如果您需要能够从应用程序中的任何位置打开模态并且不取消呈现当前路由,那么这是您的少数选择之一。

    选项 2:如果您需要可以从任何地方打开的 URL 绑定模式

    对于当前的项目,我通过使用查询参数做了一些适用于这个用例的事情。对我来说,这感觉有点 hacky,但到目前为止它在我的测试中运行良好(社区中的其他人 - 如果您对此有意见,请告诉我)。本质上,它看起来像这样:

    App.ApplicationController = Ember.Controller.extend({
       queryParams: ["articleId"],
       articleId: null, 
    
       article: function() {
          if(!this.get("articleId") return null;
          return this.get("store").find("article", this.get("articleId"));
       }
    });
    

    在 application.hbs 中:

    {{#if article.isFulfilled}}
        {{render "articleModal" article.content}}
    {{/if}}
    

    然后我可以使用普通的{{link-to}} 助手并链接到查询参数:

    {{#link-to (query-params articleId=article.id)}}View Article{{/link-to}}
    

    这可行,但我对这个解决方案并不完全满意。使用插座 {{outlet "article-modal"}} 并将应用程序路由渲染到其中可能会稍微干净一些,但可能需要更多 LOC。

    选项 3:如果仅从一条路线打开模式

    您可以将模态将打开的路由设置为模态路由的父级。像这样的:

    Market.Router.map(function() {
        this.resource('articles', { path: '/articles' }, function() {
            this.route('modal', { path: '/:article_id' }); 
        });
    });
    

    如果您的模态只能从单个路由中“打开”,则此方法效果很好。在上面的示例中,模态将始终在文章路由的顶部打开,如果您从应用程序中的任何其他位置链接到模态路由,文章路由将呈现在模态下方。只需确保模态的“关闭”动作将您从模态路径中转换出来,这样用户就无法关闭您的模态,但仍处于模态路径上。

    【讨论】:

      猜你喜欢
      • 2014-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-18
      相关资源
      最近更新 更多