问题
I need to re-execute javascript just after form gets re-rendered. Simply, putting in javascript after XHTML content won't help since its a partial request. Also, I cannot use "onComplete" as the commandButton from which I am re-rendering form is in JSF component used at several places. I need to get the fix in locally.
Is there any way? I was wondering whether f:ajax would help in this case.
Please let me know, if anyone has clue about it.
回答1:
Simplest way is to just put the JS function call in the to-be-updated component itself.
<h:form>
...
<h:commandButton value="submit"><f:ajax render="@form" /></h:commandButton>
<h:outputScript>someFunction();</h:outputScript>
</h:form>
This way it's executed as the page loads and also if the form get updated by ajax.
As to the <f:ajax>
itself, you could also use its onevent
attribute.
<f:ajax ... onevent="handleAjax" />
with
function handleAjax(data) {
var status = data.status;
switch(status) {
case "begin":
// This is invoked right before ajax request is sent.
break;
case "complete":
// This is invoked right after ajax response is returned.
break;
case "success":
// This is invoked right after successful processing of ajax response and update of HTML DOM.
someFunction();
break;
}
}
You could add a global hook by jsf.ajax.addOnEvent()
so that you don't need to specify it in every single onevent
attribute of <f:ajax>
if the functional requirement applies to every ajax request.
jsf.ajax.addOnEvent(handleAjax);
An alternative is to use the OmniFaces JSF utility library which offers the <h:onloadScript> for exactly this purpose. You can place it in the head so you want.
<h:onloadScript>someFunction();</h:onloadScript>
This is automatically re-excuted on every single ajax request on the view so that you don't need to copy it over multiple individual places in the view which can be ajax-updated, or to repeat its parent ID in every <f:ajax render>
.
回答2:
BalusC first answer is the most appropriate if you want to do complex operations with JQuery/JS and are not particularly concerned about this
For more complex JS, if you decide to use a global event handler and for example you use JS to bind
functions to elements, these functions are going to be re-bound (hence executed twice), so you need some way to identify what needs to be re-executed.
What I finally did, was to get the id's from the event callback and execute only the relevant JS/JQuery:
jsf.ajax.addOnEvent(ajaxCompleteProcess);
function ajaxCompleteProcess(data) {
if (data.status && data.status === 'success') {
var children1 = data.responseXML.children;
for (i = 0; i < children1.length; i += 1) {
var children2 = children1[i].children;
for (j = 0; j < children2.length; j += 1) {
var children3 = children2[j].children;
for (y = 0; y < children3.length; y += 1) {
if (children3[y].id.indexOf('javax.faces.ViewState') != -1)
continue;
elementProcess(('#' + children3[y].id.replace(/\:/g, '\\:')));
}
}
}
}
}
Note: these ugly for
loops are probably not required (you could use clildren[0]), but I haven't found the time yet to check the spec.
回答3:
You could add jQuery to your application and do something like:
$(#yourComponentId).load(function(){
//execute javascript.
});
You can take a look here http://api.jquery.com/load/
LE: that being on
$(document).ready(function(){
}
ofc.
来源:https://stackoverflow.com/questions/13081129/how-to-re-execute-javascript-function-after-form-rerender