3

我有一个仅在 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是组件生成的Javascript函数<h:commandLink/>

问题是document.forms["foobar"]最初呈现页面时运行良好,但一旦在 Ajax 调用后重新呈现表单,此代码就不再适用于 Firefox(但适用于 IE6)。

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

请注意,如果我document.getElementById("foobar");在 Ajax 调用之后调用,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元素(特别是我的表单),从而将其从数组中删除。然后,它再次添​​加带有新内容的表单。但是 Firefox 不会更新数组,而 IE6 会。这就是在 Ajax 调用之后返回的原因。foobardocument.formsfoobardocument.formsdocument.forms["foobar"]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);
};

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

4

2 回答 2

2

从我所看到的来看,这个问题实际上是一个 HTML 问题。

您的表单应使用名称定义,而不仅仅是 id 属性:

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

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

于 2010-01-08T03:19:40.340 回答
0

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

于 2010-01-08T11:53:15.440 回答