我过去几天一直试图解决一个非常恼人的问题,我终于承认失败了,并且对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问题,但这不起作用。
有谁知道可能发生的事情?
答案 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);
};