1

在过去的几天里,我一直在尝试解决一个非常烦人的问题,我终于承认失败,并呼吁 SO。

首先,我将概述我正在尝试做的事情,然后我将详细说明我遇到问题的地方。

目标: 用户正在填写表单,如果表单上的任何元素发生更改并且用户尝试离开表单而不保存更改,则模式应显示以下消息:

您已对此记录进行了更改。是否要保存更改?

用户得到一个是/否/取消选项。

如果用户选择:

是:记录应该保存,然后导航到最初预期的路线。

否:不应保存记录,应将用户导航到预期路线。

取消:模式应该关闭,用户将保持在当前页面上,不会更改路线。

我正在使用backbone.routefilter库在路由更改发生之前检测路由更改。

问题:

为了解决这个问题,我initialize在包含表单的视图中的方法中放置了一个路由更改侦听器。以下是该代码:

// If the user tries go to a different section but the record has been changed, confirm the user action
    app.circulationRouter.before = function( route, params ) {
        app.fn.clearNotifications();
        if(app.recordChanged){
            var confirmView = new app.views.confirm({
                header:"Patron Record Changed",
                bodyText:"You have made changes to this record. Do you want to save the changes?",
                trueLabel:"Yes",
                falseLabel:"No",
                cancelLabel:"Cancel",
                hasTrue:true,
                hasFalse:true,
                hasCancel:true,
                trueCallback:function(){
                    // Ignore the patron record change
                    _this.saveRecord();

                    // Render the patron section AFTER the save
                    _this.model.on({
                        'saved' : function(){
                            // Render the new seciton
                            app.circulationRouter.renderPatronSection(_this.model, params[1]);
                            app.currentPatronSection = params[1];

                            // Set the record changed to false
                            app.recordChanged = false;

                            // Remove the 'before' listener from the circulationRouter
                            app.circulationRouter.before = function(){};

                            if(con)console.log('in saved');

                            // Remove the listener
                            _this.model.off('saved');
                        },
                        'notsaved' : function(){
                            // Stay on the patron record page, keep the url at record
                            app.circulationRouter.navigate("patrons/"+_this.model.get('PatronID')+"/record",false);
                            _this.model.off('notsaved');
                        }
                    }, _this);

                },
                falseCallback:function(){
                    if(con)console.log(params);
                    if(params.length){
                        // Ignore the patron record change
                        app.circulationRouter.renderPatronSection(_this.model, params[1]);
                        app.currentPatronSection = params[1];
                    }else{
                        if(con)console.log('blah');
                        setTimeout(function(){
                            if(con)console.log('should navigate');
                            app.circulationRouter.navigate("", true);
                        }, 5000);
                    }
                    app.recordChanged = false;
                    app.circulationRouter.before = function(){};
                },
                cancelCallback:function(){
                    // Stay on the patron record page, keep the url at record
                    app.circulationRouter.navigate("patrons/"+_this.model.get('PatronID')+"/record",false);
                }

            });
            app.el.append(confirmView.render().el);
            return false;
        }
    };

这三个选项中的每一个都有一个回调,该回调在将控制结果的初始化函数中调用。Cancel按钮的行为总是正确的。我遇到的问题是用户想要导航到主页时,即调用此行时:app.circulationRouter.navigate("", true);。如果有一个新的、已定义的导航路线,其他一切都会正常工作。

以下是导致问题的事件序列:

1) 修改记录

2)尝试导航到主页

3) 路由改了首页路由,但是记录还在

4)模态自动显示,三个选项

5) 选择按钮

6) falseCallback 被触发

7) 模态框关闭,记录页面仍保留视图,但浏览器中显示的路线是主页

#7 的预期行为是显示主页的视图,但只有 url 反映了这一点。您可以在falseCallback我什至尝试延迟重定向触发器以确保它不是 DOM 问题中看到,但这不起作用。

有谁知道可能会发生什么?

4

1 回答 1

0

这就是问题所在。一旦路线改变,如果您重新导航到相同的路线,即使您设置了 param {trigger:true},页面也不会重新加载。这里有一个很长的讨论。

根据 github 中列出的讨论,我正在使用此解决方案并添加refresh选项。如果刷新选项设置为 true,那么即使 url 没有改变,视图也会重新加载。否则,功能保持不变。

_.extend(Backbone.History.prototype, {
            refresh: function() {
                this.loadUrl(this.fragment);
            }
        });

var routeStripper = /^[#\/]/;
var origNavigate = Backbone.History.prototype.navigate;
Backbone.History.prototype.navigate = function (fragment, options) {
    var frag = (fragment || '').replace(routeStripper, '');
    if (this.fragment == frag && options.refresh)
        this.refresh();
    else
        origNavigate.call(this, fragment, options);
};
于 2013-09-18T14:03:07.693 回答