Backbone-route click在第二次尝试时没有响应

时间:2013-02-05 20:17:34

标签: backbone.js validation

当用户想要预览由路线调用的发票时,我正在函数中进行表单验证:

routes: {
        "new"                   : "newInvoice",
        "new/:assignmentid"     : "newInvoiceAssignment",
        "edit/:invoiceid"       : "editInvoice",
        "preview/:invoiceid"    : "previewInvoice",
        "preview"               : "preview",
        "delete/:invoiceid"     : "deleteInvoiceModal",
        "whyCant"               : "whyCant",
        "whatsThis"             : "whatsThis"
    },

这是表格上的两个按钮(实际上是一个按钮和一个href):

<div class="span8 alignRight">
    <button id="saveInvoiceDraft" type="submit" class="btn btn-warning">Save Draft</button>
    <a id="previewInvoice" class="btn btn-primary">Preview &amp; Send</a>
</div>

创建此发票后,标记的URL设置为:

var url = '#preview';
$('#previewInvoice').attr('href',url);

最后,当我点击“预览和发送”按钮时,下面的previewInvoice(invoiceid)函数运行,正确捕获缺少的一个表单字段并显示错误消息。在那时,即使我填充表单字段,该按钮已经死亡,不再响应。但是,“保存草稿”按钮可以完美地工作,并且模仿与previewInvoice()函数中相同的代码。

我知道可能有更好的方法可以做到这一点,但我是按照这种方式在我继承的应用程序的另一部分完成的。实际上,当我输入这个时,我想知道因为sendDraft()函数工作并且它的按钮和previewInvoice()函数没有,所以它是一个href的事实可能与它有关。

function previewInvoice(invoiceid) {
    var invoice = new Invoice({"invoiceid": invoiceid});
    invoice.set({"invoiceid": invoiceid,"invoicestatus": "draft"});
    formGetter(invoice);
    validateInvoiceForm(invoice);

    if (window.errors.length == 0) {
        //business logic here

        if (window.panel == undefined) {
            // business logic here
        }
        else {
            //save business logic here
        }
    }
    else {
        showInvoiceErrors();
    }
}

为什么按钮不再响应的任何想法?我没有在控制台中看到任何错误。我在函数内部添加了一个consol.log来显示不同表单元素的值,它在控制台中第一次显示,但如果我更改数据并再次单击该按钮,则该日志不会更新,这对我来说是另一个线索,它只是没有开火。

3 个答案:

答案 0 :(得分:1)

Backbone.History侦听hashchange个事件以触发导航到路线。首次单击previewInvoice按钮时,URL哈希片段将设置为#preview,并触发匹配的路由。

当你第二次点击同一个按钮时,哈希实际上没有改变,因此路由器没有捕获它。

我很难为这个问题推荐一个好的解决方案。通常我会建议捕获click事件并手动调用router.navigate("preview", {trigger:true});。但是,根据您的代码示例,您的应用程序看起来像Router,并且没有View层用于DOM事件处理,正如您在大多数Backbone应用程序中所期望的那样。

在路由器级别上,解决这个问题有点棘手。在router.navigate路由执行后,您可以使用preview设置虚拟哈希。这将导致链接第二次触发hashchange。不幸的是,这意味着preview页面不会被收藏,而且由于您没有使用pushState,因此会留下无关的历史记录条目。

我担心这个问题必须通过hacky修复(如上所述)或重大重构来解决。

答案 1 :(得分:1)

我有同样的问题,我的解决方案是放入一个处理程序,它执行从历史中隐藏的虚假“中间”路由,以便Backbone.history将导航注册为更改并触发操作。

将一个类放在需要路由操作触发的链接上,无论URL是否相同:

<a href="/someaction" class="js-ensureNav">do it</a>

在Backbone视图中,输入一个事件处理程序:

events: {
    "click .js-ensureNav": "_ensureNav",
},

实际处理程序:

_ensureNav: function (event) {
    var route_name = $(event.target).attr('href').slice(1);
    Backbone.history.navigate("fake");
    Backbone.history.navigate(route_name, {trigger: true, replace: true});
},

答案 2 :(得分:1)

而不是

var url =&#39; #preview&#39;;

$(&#39;#previewInvoice&#39;)ATTR(&#39; HREF&#39;,URL);

试试这个

var date = new Date();

var url =&#39; #preview?date:&#39; +日期;

$(&#39;#previewInvoice&#39;)ATTR(&#39; HREF&#39;,URL);

因此每次生成新请求时都会解决您的问题。