【问题标题】:JSF CommandLink does not work on Firefox after a whole form reRender整个表单重新渲染后,JSF CommandLink 在 Firefox 上不起作用
【发布时间】:2010-12-20 05:16:27
【问题描述】:

我有一个仅在 IE6 浏览器上使用的 JSF 1.2 应用程序(Sun RI、Facelets、Richfaces)。现在,我们还必须支持 Firefox(是的!)。

在我的一个页面中,我有一个包含一个按钮的表单,该按钮将重新呈现整个表单。重新渲染后,在这个表单中添加了一些链接(<h:commandLink/>)。

JSF 代码如下所示:

<h:form id="foobar">
    ...
    <a4j:commandButton ... reRender="foobar"/>
    ...
    <h:commandLink .../>
</h:form>

我的问题与命令链接组件生成的HTML代码有关,如下:

<a href="#" onclick="if(typeof jsfcljs == 'function'){jsfcljs(document.forms['foobar'],'...','');}return false">bla bla</a>

(供参考,jsfcljs是组件&lt;h:commandLink/&gt;生成的Javascript函数)

问题是document.forms["foobar"]在页面初始渲染时运行良好,但一旦在Ajax调用后重新渲染表单,此代码在Firefox上不再工作(但在IE6上工作)。

当我在 Ajax 调用后单击表单中的一个链接时,这会导致 Javascript 错误。

请注意,如果我在 Ajax 调用之后调用 document.getElementById("foobar");,Firefox 会找到我的表单...

如果您考虑以下 Javascript 函数:

function test() {
    var e = document.forms;
    var tmp = "";
    for (i = 0; i < e.length; i++) {
        tmp = tmp + e[i].id + " ; ";
    }
    alert(tmp);
}

当我在 Ajax 调用之前和之后运行它时,我得到以下结果:

someForm ; anotherForm ; foobar ; // Before Ajax call on FF 
someForm ; anotherForm ; // After Ajax call on FF. PROBLEM HERE!

someForm ; anotherForm ; foobar ; // Before Ajax call on IE6 
someForm ; anotherForm ; foobar ; // After Ajax call on IE6

以下是我对问题原因的看法:

当在客户端收到 Ajax 响应时,a4j 将从 DOM 树对象中删除 reRender 元素(尤其是我的foobar 表单),从而将其从document.forms 数组。 然后,它再次添​​加带有新内容的foobar 表单。但是 Firefox 确实不更新 document.forms 数组,而 IE6 会。 这就是 document.forms["foobar"] 在 Ajax 调用后返回 undefined 的原因。

我解决此问题的解决方案是更改reRender 属性,以便仅重新渲染表单的子部分,而不是表单本身。这样,我的链接就可以工作了。

但是,我想知道是否有其他方法可以解决此问题,而无需修改 reRender 属性。 有什么想法吗?


编辑

点击命令链接时的Javascript代码如下:

function dpf(f) {
    var adp = f.adp;
    if (adp != null) {
        for (var i = 0; i < adp.length; i++) {
            f.removeChild(adp[i]);
        }
    }
};

function apf(f, pvp) {
    var adp = new Array();
    f.adp = adp;
    var ps = pvp.split(',');
    for (var i = 0, ii = 0; i < ps.length; i++, ii++) {
        var p = document.createElement("input");
        p.type = "hidden";
        p.name = ps[i];
        p.value = ps[i + 1];
        f.appendChild(p);
        adp[ii] = p;
        i += 1;
    }
};

function jsfcljs(f, pvp, t) {
    apf(f, pvp);
    var ft = f.target;
    if (t) {
        f.target = t;
    }
    f.submit();
    f.target = ft;
    dpf(f);
};

在&lt;h:commandLink&gt; onclick 属性中,我们调用在jsfcljs(undefined, 'someId', '') 中评估的jsfcljs(document.forms['foobar'], 'someId', '')。然后,当调用 f 时,我收到一个 Javacript 错误,上面写着 f is undefined。

【问题讨论】:

    标签: javascript ajax jsf richfaces


    【解决方案1】:

    问题实际上是我所看到的 HTML 问题。

    您的表单应该使用名称而不是简单的 id 属性来定义:

    不同的浏览器会以不同的方式处理 name 和 id 等效项。如果这不能解决您的问题评论,我将生成一个不需要服务器端来演示您所看到的任何效果的测试用例。

    解决问题代码的另一种方法是在客户端重写内联 onclick 事件调用,以便使用 document.getElementById("foobar") 调用而不是 document.forms["foobar" 通过 id 引用表单]

    【讨论】:

    • 感谢您在 id 属性之外使用 name 的想法。我会尽快检查的!关于您修改内联onclick 函数的提议,这是不可想象的,因为此JS 代码是由JSF 核心生成 的。但是,正如 BalusC 所述,此代码可能自最新版本的 JSF 1.2 以来已经发展...
    • 这些功能可以被页面中嵌入的其他javascript代码修改。如果事实证明这是必要的,我可能会提供完成此任务的代码。
    • 我在 Chrome 进行重新渲染时遇到了类似的问题,但 Firefox 拒绝重新渲染。在表单中添加 name 没有帮助。
    【解决方案2】:

    我记得这是 Sun Mojarra 1.2 的错误之一(已经存在 4 年了)。升级库应该可以解决这个问题。目前最新的 Sun Mojarra 1.2 是 1.2_14,仅在三周前发布。只需将/WEB-INF/lib 中的两个 JSF 库替换为它们即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-28
      • 1970-01-01
      • 2011-03-30
      相关资源
      最近更新 更多