I'm building on BalusC's solution to highlight and focus fields in JSF. My plan is to output a JSON array with ids and then have a method be called which will process this array. This works fine when I don't use <f:ajax/>
Here is my phase listener solution:
public void beforePhase(PhaseEvent event) {
FacesContext facesContext = event.getFacesContext();
List<String> highlightFields = new ArrayList<String>();
Iterator<String> highlightFieldsItr = facesContext
.getClientIdsWithMessages();
while (highlightFieldsItr.hasNext()) {
StringBuilder sb = new StringBuilder();
sb.append("#");
sb.append(highlightFieldsItr.next().replaceAll(":", "\\\\:"));
highlightFields.add(sb.toString());
}
JSONArray jsonHighlightFields = new JSONArray(highlightFields);
facesContext.getExternalContext().getRequestMap()
.put("errorFields", jsonHighlightFields.toString());
}
Basically this would produce errorFields value with something like ["#some\:id1", "#some\id2"]. Then I can do something like this in my root layout file:
<script>
var errorFields = ${errorFields}; // This will xlate to ["#some\\:id1", "#some\\:id2"
$(document).ready(function(){
processInputErrors(errorFields);
});
</script>
With a processInputErrors function like this:
function processInputErrors(ids) {
for (id in ids) {
if (focus == false) {
jQuery(ids[id]).focus();
focus = true;
}
jQuery(ids[id]).addClass('input-error');
}
}
However, I need to somehow obtain this list in the function which gets called on success of an ajax post.
Now f:ajax does have the onevent attribute and this function does get called, but I'm not sure exactly what it gets passed. How would I be able somehow pass the invalid Ids from the phase listener to this function? It seems to be passed an object which represents the HTMLInputElement?
<f:ajax event="change" onevent="test" render="test test_msg" immediate="true" />
Happy to hear about alternative suggestions or ideas. The goal is basically to focus and highlight the field(s) which are invalid not only on a full post-back but also when using f:ajax.
Thanks!
That article was more targeted on JSF 1.x. JSF 2.x offers now a lot of advantages of which the following are beneficial for your particular requirement:
- You can refer the current component in EL by
#{component}
. In case of input components this is theUIInput
which in turn has anisValid()
method. This could be used instyleClass
attribute. - You can use
<f:ajax>
to re-render parts of the view, also<script>
elements.
1+1 is...
<h:inputText id="input1" value="#{bean.input1}" required="true" styleClass="#{component.valid ? '' : 'error'}">
<f:ajax render="@this input1message focus" />
</h:inputText>
<h:message id="input1message" for="input1" />
...
<h:inputText id="input2" value="#{bean.input2}" required="true" styleClass="#{component.valid ? '' : 'error'}">
<f:ajax render="@this input2message focus" />
</h:inputText>
<h:message id="input2message" for="input2" />
...
<h:panelGroup id="focus"><script>jQuery(":input.error:first").focus();</script></h:panelGroup>
No need for a PhaseListener
anymore. You could if necessary wrap the input markup boilerplate in a composite component or a tag file.
Back to your concrete question about the onevent
attribute, check this answer: JSF 2: How show different ajax status in same input?
来源:https://stackoverflow.com/questions/7296259/jsf-field-highlighting-with-ajax-posts