简体   繁体   English

Emberjs Modal作为路线

[英]Emberjs Modal as a route

I am trying to figure out how to convert a route into a modal, such that you can navigate to it via any other route WHILE preserving underlying(previous) template. 我试图弄清楚如何将路线转换为模态,以便您可以通过任何其他保留基础(上一个)模板的路线来导航至该路线。

For example: 例如:

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

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

http://example.com/site/article/1234 goes to article.hbs if user comes from another domain(fresh start) 如果用户来自另一个域,则http://example.com/site/article/1234转到article.hbs(重新开始)

BUT http://example.com/site/article/1234 opens up article.hbs inside the "article-modal" outlet if user comes any other route. 但是,如果用户有其他路线,则http://example.com/site/article/1234会在“ article-modal”出口内打开article.hbs。

Here is the router.js 这是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: '*:' });
});

here is application.hbs 这是application.hbs

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

and here is article.js route Alternative case #1 这是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;
}
}
});

and here is article.js route Alternative case #2 这是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);
},
});

Problem with case #1 is that browser address bar does not reflect current route. 情况1的问题是浏览器地址栏未反映当前路由。 If user goes from index route to article route the browser address bar still shows /index.. So if he presses back button app breaks. 如果用户从索引路径转到文章路径,浏览器地址栏仍显示/ index ..因此,如果他按返回按钮,则应用程序中断。

Problem with case #2 is that it discards the contents of index.hbs because the article route is not nested. 情况2的问题在于,它会丢弃index.hbs的内容,因为文章路由未嵌套。

Is it possible to even have such functionality with Ember? Ember是否有可能具有这种功能?

Thanks :) 谢谢 :)

Edit: Just re-read OP's question and realized I didn't understand his question, so I created a new answer ( https://stackoverflow.com/a/27948611/1010074 ) outlining another approach that I came up with after experimenting with something. 编辑:重新阅读OP的问题并意识到我不理解他的问题,所以我创建了一个新的答案( https://stackoverflow.com/a/27948611/1010074 ),概述了我尝试过的另一种方法一些东西。

Option 1: Ember's suggested method for handling Modals 选项1:Ember建议的处理模式的方法

The Ember website has a "cookbook" for how they recommend handling modal dialogs: http://emberjs.com/guides/cookbook/user_interface_and_interaction/using_modal_dialogs/ Ember网站上有一本“菜谱”,介绍了他们如何建议处理模式对话框: http : //emberjs.com/guides/cookbook/user_interface_and_interaction/using_modal_dialogs/

Essentially, you would create an action in a route that opens the modal: 本质上,您将在打开模式的路径中创建一个动作:

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

And then call this.send("openArticleModal", article) either from your controller / another route or you could do something like <button {{action "openArticleModal" article}}>View Artice</button> in your template. 然后从您的控制器/另一条路线调用this.send("openArticleModal", article) ,或者您可以在模板中执行类似<button {{action "openArticleModal" article}}>View Artice</button>的操作。

Essentially this method takes the modal out of a routed state, which means the modal won't be URL bound, however if you need to be able to open the modal from anywhere in the app and not un-render the current route, then it's one of your few options. 从本质上讲,此方法将模式从路由状态中移除,这意味着该模式将不受URL限制,但是,如果您需要能够从应用程序中的任何位置打开模式,而又不取消渲染当前路径,则它是您的少数选择之一。

Option 2: If you need URL-bound modals that can be opened from anywhere 选项2:如果您需要可以在任何地方打开的URL绑定模式

For a current project, I have done something that works for this use case by using query params. 对于当前项目,我已经通过使用查询参数完成了一些适用于该用例的工作。 To me, this feels a little hacky, but it works fairly well in my tests so far (others in the community - if you have opinions on this, please let me know). 对我来说,这有点怪异,但到目前为止,在我的测试中它还是相当不错的(社区中的其他人-如果对此有意见,请告诉我)。 Essentially, it looks like this: 本质上,它看起来像这样:

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"));
   }
});

In application.hbs: 在application.hbs中:

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

Then I can use normal {{link-to}} helpers and link to the query param: 然后,我可以使用常规的{{link-to}}助手并链接到查询参数:

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

This works, but I'm not entirely happy with this solution. 这可行,但是我对这种解决方案并不完全满意。 Something slightly cleaner might be to use an outlet {{outlet "article-modal"}} and have the application route render into it, but it might take more LOC. 稍微干净一点的方法可能是使用出口{{outlet "article-modal"}}并在其中渲染应用程序路由,但是这可能会花费更多的LOC。

Option 3: If the modal is only ever opened from one route 选项3:如果仅从一条路线打开模态

You can make the route that the modal will open into a parent of the modal route. 您可以将模态将打开的路径设为模态路径的父级。 Something like this: 像这样:

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

This works well if your modal can only "open" from within a single route. 如果您的模态只能在一条路径内“打开”,则此方法效果很好。 In the example above, the modal will always open on top of the articles route, and if you link-to the modal route from anywhere else in the app, the articles route will render underneath the modal. 在上面的示例中,模态将始终在文章路径的顶部打开,并且如果您从应用程序中的其他任何位置链接到模态路径,则文章路径将在模态下方呈现。 Just make sure that the "close" action of your modal transitions you out of the modal route, so a user can't close your modal but and still be on the modal route. 只要确保您的模态的“关闭”操作使您退出模态路线,那么用户就无法关闭您的模态,但仍然处于模态路线上。

This is my second answer to this question. 这是我对这个问题的第二个回答。 My original answer ( https://stackoverflow.com/a/27947475/1010074 ) didn't directly answer OP's question, however, I outlined three other approaches to handling modals in Ember in that answer and am leaving it there in case it's helpful to anyone else. 我最初的答案( https://stackoverflow.com/a/27947475/1010074 )没有直接回答OP的问题,但是,我在该答案中概述了在Ember中处理模态的其他三种方法,如果有帮助,请保留其中给其他人。

Solution: define multiple routes with the same path 解决方案:使用同一路径定义多个路由

While Ember doesn't usually allow you to define two routes that use the same path, you can actually have a nested route and an un-nested route with the same effective path, and Ember works with it just fine. 尽管Ember通常不允许您定义两条使用同一路径的路由,但实际上您可以具有一个嵌套的路由和一个具有相同有效路径的非嵌套路由,而Ember可以很好地使用它。 Building off of option 3 from my original answer, I have put together a proof of concept that I think will work for you. 在我最初回答的选项3的基础上,我整理了一个概念证明,认为对您有用。 Here's a JS Fiddle: http://jsfiddle.net/6Evrq/320/ 这是一个JS小提琴: http : //jsfiddle.net/6Evrq/320/

Essentially, you can have a router that looks something like this: 本质上,您可以拥有一个如下所示的路由器:

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

And within your templates, link to the index.articleModal route: 在模板中,链接到index.articleModal路由:

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

Since articleModal renders inside of index , your index route isn't un-rendered. 由于articleModal呈现在index内部,因此您的index路由不会未呈现。 Since the URL path changes to /article , a reload of the page will route you to your regular Article route. 由于URL路径更改为/article ,因此页面的重新加载会将您引导到常规的Article路由。

Disclaimer: I am unsure if this is exploiting a bug in current Ember or not, so mileage here may vary. 免责声明:我不确定这是否正在利用当前Ember中的错误,因此此处的里程可能会有所不同。

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

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