使用Meteor iron路由器中止导航
我在Meteor应用程序中有一个(客户端)路由器,以及使用使用Meteor iron路由器中止导航,meteor,iron-router,Meteor,Iron Router,我在Meteor应用程序中有一个(客户端)路由器,以及使用{{{pathFor}}帮助程序的链接 当用户更改表单字段时,我正在会话中设置一个dirty标志,我想触发一个警告,并允许用户在设置标志时停止导航离开页面,基本上类似于onunload处理程序 我试着用以下方法来实现这一点: Router.onBeforeAction(function(pause) { var self = this; if (!this.ready()) { return; }
{{{pathFor}}
帮助程序的链接
当用户更改表单字段时,我正在会话
中设置一个dirty
标志,我想触发一个警告,并允许用户在设置标志时停止导航离开页面,基本上类似于onunload
处理程序
我试着用以下方法来实现这一点:
Router.onBeforeAction(function(pause) {
var self = this;
if (!this.ready()) {
return;
}
if(Session.get('dirty')) {
if(!confirm("Are you sure you want to navigate away?")) {
pause();
}
}
});
然而,当我得到提示时,我仍然被导航离开。也就是说,pause()
似乎不会停止后续的路由器操作,不管它是什么
我做错了什么?你想去什么地方?还有Router.go(routeName),它将使页面指向给定的routeName。我想说的是,也许你可以强制路由器转到当前页面,从而忽略返回操作。从我可以看出,这在iron Router API中是不可能的。但是,您可以这样覆盖Router.go方法(在客户端代码中的某个地方):
var go=Router.go;//缓存原始Router.go方法
Router.go=函数(){
if(Session.get('dirty')){
如果(确认(“您确定要离开吗?”)){
去应用(这个,论点);
}
}否则{
去应用(这个,论点);
}
};
iron router的新行为应该会使这更容易,因为它需要调用onBeforeAction钩子(请参阅)中的this.next()
,因此只有在会话未脏或用户确认警告时才调用它:
if(Session.get('dirty')) {
if(confirm("Are you sure you want to navigate away?")) {
this.next();
}
} else {
this.next();
}
我发现在
stop
中重新选择有效,即使您没有通过Router.go
(例如通过我的应用程序中的链接)更改路由也有效
下面是一个coffeescript实现,它使用的类继承自RouteControl
类MyRouteControl扩展了RouteControl
停止:->
#保存您的数据/表单是否脏或处于何种状态
#会话变量。
if Session.get('formsdirty')
如果!确认('您有未保存的数据。确实要离开吗?')
#重定向到当前路线将停止当前导航。
#尽管如此,它确实会重新运行路由,因此它不是一个完美的解决方案。
Router.go'/my\u route'
#返回此处,这样我们就不再执行任何停止操作。
返回
#否则就照常做。
超级的
Iron Router API并没有提供一种简单的方法来实现这一点。无法取消从onBeforeAction
hook进行的转换。必须通过重定向到上一条路线来解决此问题
/*
* Adds a confirmation dialogue when the current route contains unsaved changes.
*
* This is tricky because Iron Router doesn't support this out of the box, and
* the reactivity gets in the way.
* In this solution, redirecting to the current route is abused
* as a mechanism to stop the current transition, which Iron Router has no API
* for. Because the redirect would trigger the onStop hook, we keep track of
* whether to run the onStop hook or not ourselves in
* `skipConfirmationForNextTransition`.
*
* When `Session.get('formIsDirty')` returns `true`, the user will be asked
* whether he really wants to leave the route or not.
*
* Further, another confirmation is added in case the browser window is closed
* with unsaved data.
*
* This gist shows the basics of how to achieve a navigation confirmation,
* also known as canceling a route transition.
* This approach may fail if other route hooks trigger reruns of hooks reactively.
* Maybe setting `skipConfirmationForNextTransition` to `true` could help in those
* cases.
*/
Session.setDefault('formIsDirty', false)
const confirmationMessage = 'You have unsaved data. Are you sure you want to leave?'
// whether the user should confirm the navigation or not,
// set to `true` before redirecting programmatically to skip confirmation
let skipConfirmationForNextTransition = false
Router.onStop(function () {
// register dependencies immediately
const formIsDirty = Session.equals('formIsDirty', true)
// prevent duplicate execution of onStop route, because it would run again
// after the redirect
if (skipConfirmationForNextTransition) {
skipConfirmationForNextTransition = false
return
}
if (formIsDirty) {
const shouldLeave = confirm(confirmationMessage)
if (shouldLeave) {
Session.set('formIsDirty', false)
return
}
// obtain a non-reactive reference to the current route
let currentRoute
Tracker.nonreactive(function () {
currentRoute = Router.current()
})
skipConfirmationForNextTransition = true
// "cancel" the transition by redirecting to the same route
// this had to be used because Iron Router doesn't support cancling the
// current transition. `url` contains the query params and hash.
this.redirect(currentRoute.url)
return
}
})
// Bonus: confirm closing of browser window
window.addEventListener('beforeunload', event => {
if (Session.get('formIsDirty')) {
// cross-browser requries returnValue to be set, as well as an actual
// return value
event.returnValue = confirmationMessage // eslint-disable-line no-param-reassign
return confirmationMessage
}
})
可以找到最新版本。我希望用户不要离开页面,即我要中止路由。先生,您是个天才。:)如果有一个稍微不那么老套的方法来做这件事,那就太好了,但这确实有效。