Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Meteor iron路由器中止导航_Meteor_Iron Router - Fatal编程技术网

使用Meteor iron路由器中止导航

使用Meteor iron路由器中止导航,meteor,iron-router,Meteor,Iron Router,我在Meteor应用程序中有一个(客户端)路由器,以及使用{{{pathFor}}帮助程序的链接 当用户更改表单字段时,我正在会话中设置一个dirty标志,我想触发一个警告,并允许用户在设置标志时停止导航离开页面,基本上类似于onunload处理程序 我试着用以下方法来实现这一点: Router.onBeforeAction(function(pause) { var self = this; if (!this.ready()) { return; }

我在Meteor应用程序中有一个(客户端)路由器,以及使用
{{{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
  }
})

可以找到最新版本。

我希望用户不要离开页面,即我要中止路由。先生,您是个天才。:)如果有一个稍微不那么老套的方法来做这件事,那就太好了,但这确实有效。