骨干路由器不会触发视图更改

时间:2013-09-12 17:44:26

标签: javascript backbone.js backbone-routing

我过去几天一直试图解决一个非常恼人的问题,我终于承认失败了,并且对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;
        }
    };

三个选项中的每一个都有一个回调函数,该函数将在初始化函数中调用,该函数将控制结果。 取消按钮始终表现正常。我遇到的问题是当用户想要导航到主页时,即调用此行时:app.circulationRouter.navigate("", true);。如果有新的,定义的路线要导航,则其他所有工作都能正常工作。

以下是产生问题的事件序列:

1)修改记录

2)尝试导航到主页

3)路线改变了主页路线,但记录仍在视线中

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

5)选择按钮

6)触发了falseCallback

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

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

有谁知道可能发生的事情?

1 个答案:

答案 0 :(得分:0)

这是问题所在。路径更改后,如果您重新导航到同一路由,即使设置了参数{trigger:true},页面也不会重新加载。关于它的讨论很长here

根据github中列出的讨论,我使用此解决方案并添加refresh选项。如果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);
};