Emberjs 模态作为路线
Emberjs Modal as a route
我正在尝试弄清楚如何将路由转换为模式,这样您就可以通过任何其他路由导航到它,同时保留底层(以前的)模板。
例如:
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 实现这样的功能?
谢谢:)
编辑:重新阅读 OP 的问题并意识到我不理解他的问题,所以我创建了一个新答案 (),概述了我在尝试某些东西后想出的另一种方法。
选项 1:Ember 处理模态框的建议方法
Ember 网站有一个 "cookbook" 推荐如何处理模态对话框:
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)
,或者您可以在模板中执行类似 <button {{action "openArticleModal" article}}>View Artice</button>
的操作。
本质上,此方法使模态脱离路由状态,这意味着模态不会 URL 绑定,但是如果您需要能够从应用程序中的任何位置打开模态而不是取消渲染当前路线,那么它就是您的几个选项之一。
选项 2:如果您需要可以从任何地方打开的 URL 绑定模式
对于当前的项目,我通过使用查询参数做了一些适用于这个用例的事情。对我来说,这感觉有点老套,但到目前为止,它在我的测试中运行良好(社区中的其他人 - 如果您对此有意见,请告诉我)。本质上,它看起来像这样:
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 查询参数:
{{#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' });
});
});
如果您的模态框只能从一条路线中 "open",这很有效。在上面的示例中,模态窗口将始终在文章路径的顶部打开,如果您 link- 从应用程序中的其他任何位置转到模态路径,文章路径将呈现在模态路径下方。只需确保模态的 "close" 操作将您从模态路线中转移出来,这样用户就无法关闭模态但仍处于模态路线上。
这是我对这个问题的第二个回答。我最初的回答 () 没有直接回答 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"});
});
并在您的模板中,link 到 index.articleModal
路线:
{{#link-to "index.articleModal"}}View article!{{/link-to}}
由于 articleModal
在 index
内部呈现,您的 index
路线并非未呈现。由于 URL 路径更改为 /article
,因此重新加载页面会将您引导至常规 Article
路径。
免责声明:我不确定这是否是在利用当前 Ember 中的错误,因此这里的里程数可能会有所不同。
我正在尝试弄清楚如何将路由转换为模式,这样您就可以通过任何其他路由导航到它,同时保留底层(以前的)模板。
例如:
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 实现这样的功能?
谢谢:)
编辑:重新阅读 OP 的问题并意识到我不理解他的问题,所以我创建了一个新答案 (
选项 1:Ember 处理模态框的建议方法
Ember 网站有一个 "cookbook" 推荐如何处理模态对话框: 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)
,或者您可以在模板中执行类似 <button {{action "openArticleModal" article}}>View Artice</button>
的操作。
本质上,此方法使模态脱离路由状态,这意味着模态不会 URL 绑定,但是如果您需要能够从应用程序中的任何位置打开模态而不是取消渲染当前路线,那么它就是您的几个选项之一。
选项 2:如果您需要可以从任何地方打开的 URL 绑定模式
对于当前的项目,我通过使用查询参数做了一些适用于这个用例的事情。对我来说,这感觉有点老套,但到目前为止,它在我的测试中运行良好(社区中的其他人 - 如果您对此有意见,请告诉我)。本质上,它看起来像这样:
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 查询参数:
{{#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' });
});
});
如果您的模态框只能从一条路线中 "open",这很有效。在上面的示例中,模态窗口将始终在文章路径的顶部打开,如果您 link- 从应用程序中的其他任何位置转到模态路径,文章路径将呈现在模态路径下方。只需确保模态的 "close" 操作将您从模态路线中转移出来,这样用户就无法关闭模态但仍处于模态路线上。
这是我对这个问题的第二个回答。我最初的回答 (
解决方法:定义多条相同路径的路由
虽然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"});
});
并在您的模板中,link 到 index.articleModal
路线:
{{#link-to "index.articleModal"}}View article!{{/link-to}}
由于 articleModal
在 index
内部呈现,您的 index
路线并非未呈现。由于 URL 路径更改为 /article
,因此重新加载页面会将您引导至常规 Article
路径。
免责声明:我不确定这是否是在利用当前 Ember 中的错误,因此这里的里程数可能会有所不同。