JSF CommandLink does not work on Firefox after a whole form reRender
I have a JSF 1.2 application (Sun RI, Facelets, Richfaces) that was used only on IE6 browsers. Now, we must also support Firefox (yeah !).
In one of my pages, I have a form that contains a button that will re-render the whole form. After the re-rendering, some links (<h:commandLink/>
) are added in this form.
The JSF code looks like this:
<h:form id="foobar">
...
<a4j:commandButton ... reRender="foobar"/>
...
<h:commandLink .../>
</h:form>
My problem is related to the HTML code generated by the command link component, which is as following:
<a href="#" onclick="if(typeof jsfcljs == 'function'){jsfcljs(document.forms['foobar'],'...','');}return false">bla bla</a>
(for information, jsfcljs
is the Javascript function generated by the component <h:commandLink/>
)
The problem is that document.forms["foobar"]
is working well when the page is initially rendered, but once the form is re-rendered after the Ajax call, this code does not work anymore on Firefox (but works on IE6).
This results on a Javascript error when I click on one link in the form after the Ajax call.
Note that if I call document.getElementById("foobar");
after the Ajax call, Firefox founds my form...
If you consider the following Javascript function:
function test() {
var e = document.forms;
var tmp = "";
for (i = 0; i < e.length; i++) {
tmp = tmp + e[i].id + " ; ";
}
alert(tmp);
}
when I run it before and after the Ajax call, I get the following results:
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
Here are my thoughts about the reason of the problem:
When the Ajax response is received on the client side, a4j is removing the reRender-ed elements (in particular my foobar
form) from the DOM tree objects, which results in removing it from document.forms
array.
Then, it adds again the foobar
form with its new content. But Firefox does not update the document.forms
array, while IE6 does.
That's why document.forms["foobar"]
returns undefined
after the Ajax call.
My solution to solve this problem is to change the reRender
attribute in order to re-render only sub-parts of the form, and not the form itself. This way, my links work.
However, I wanted to know if there is another way to solve this issue, without modifying the reRender
attribute.
Any idea?
Edit
The Javascript code when a command link is clicked is the following:
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);
};
In the <h:commandLink>
onclick attribute, we call the jsfcljs(document.forms['foobar'], 'someId', '')
which is evaluated in jsfcljs(undefined, 'someId', '')
. Then, when f
is called, I get a Javacript error that says that f is undefined
.
The problem is actually an HTML one from what I see.
Your form should be defined with a name and not simply an id attribute:
Different browsers treat name and id equivalencies differently. If this does not solve your problem comment and I will produce a test case that does not require a server-side to demonstrate whatever effect you're seeing.
Another way around the problem code is to rewrite the inline onclick event calls on the client-side in order to reference the form by id with the document.getElementById("foobar") call instead of document.forms["foobar"]
I recall this as one of the bugs of Sun Mojarra 1.2 (which has already been around for 4 years). Upgrading the libs should solve this problem. The currently latest Sun Mojarra 1.2 is 1.2_14 which was released just three weeks ago. Just replace the two JSF libs in /WEB-INF/lib
with them.
精彩评论