-
Available since OmniFaces 3.7
The <o:inputHidden>
is a component that extends the standard <h:inputHidden>
and changes the behavior to immediately convert, validate and update during apply request values phase, regardless of any conversion/validation errors on other UIInput
components within the same form. The standard <h:inputHidden>
follows the same lifecycle as other UIInput
components which is in the end unintuive as hidden input fields are usually under control of the developer.
Use case 1: Imagine a form with a <h:inputHidden>
and a <h:inputText>
. The hidden input holds some prepopulated value of a request scoped bean which is intended to be passed through to the request scoped bean instance of the next request. However, when conversion/validation fails on the text input, then the hidden input won't update the bean property and then becomes empty. I.e. the original value gets permanently lost. This can be bypassed by using ajax to update only specific fields, but this will fail when the update of the hidden input is actually needed (e.g. because the value can possibly be adjusted in action/listener method).
Use case 2: Imagine a form with an UIInput
or UICommand
component whose rendered
attribute relies on a request scoped bean property which is retained for the next request through a <h:inputHidden>
. However, when Faces needs to decode the UIInput
or UICommand
component during the postback, the rendered
attribute has defaulted back to false
because the <h:inputHidden>
hasn't yet updated the request scoped bean property yet.
This behavior cannot be achieved by using immediate="true"
on <h:inputHidden>
. It would only move the conversion/validation into the apply request values phase. The model still won't be updated on time.
Also, the <h:inputHidden>
didn't support the readonly
attribute. This is however useful when used in combination with a validator which should block the form submit. Since version 4.1, the <o:inputHidden>
supports this use case by simply grabbing and validating the model value during the apply request values phase. The setter method associated with the model won't be invoked.
Usage
You can use it the same way as <h:inputHidden>
, you only need to change h:
into o:
to get the "immediate v2.0" behavior.
<h:form>
<o:inputHidden value="#{bean.hidden}" />
...
</h:form>
When using ajax, don't forget to make sure that the component is also covered by the execute
attribute.
First click "Toggle", it should show a "Submit" button whose rendered
attribute is dependent on the hidden input component, and then try clicking it. It should show a message saying "Submitted!".
With standard h:inputHidden - does not work
With OmniFaces o:inputHidden - works!
<p>First click "Toggle", it should show a "Submit" button whose <code>rendered</code> attribute is dependent on the hidden input component, and then try clicking it. It should show a message saying "Submitted!".</p>
<h3>With standard h:inputHidden - does not work</h3>
<h:form id="form">
<h:commandButton value="Toggle" action="#{inputHiddenBean.toggle1}">
<f:ajax render="panel" />
</h:commandButton>
<h:panelGroup id="panel">
<h:inputHidden value="#{inputHiddenBean.toggled1}" />
<h:commandButton value="Submit" action="#{inputHiddenBean.submit}" rendered="#{inputHiddenBean.toggled1}">
<f:ajax execute="panel" render="messages" />
</h:commandButton>
</h:panelGroup>
<h:messages id="messages" styleClass="messages" infoClass="info" warnClass="warn" errorClass="error" />
</h:form>
<h3>With OmniFaces o:inputHidden - works!</h3>
<h:form>
<h:commandButton value="Toggle" action="#{inputHiddenBean.toggle2}">
<f:ajax render="panel" />
</h:commandButton>
<h:panelGroup id="panel">
<o:inputHidden value="#{inputHiddenBean.toggled2}" />
<h:commandButton value="Submit" action="#{inputHiddenBean.submit}" rendered="#{inputHiddenBean.toggled2}">
<f:ajax execute="panel" render="messages" />
</h:commandButton>
</h:panelGroup>
<h:messages id="messages" styleClass="messages" infoClass="info" warnClass="warn" errorClass="error" />
</h:form>
package org.omnifaces.showcase.components;
import static org.omnifaces.util.Messages.addGlobalInfo;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Named;
@Named
@RequestScoped
public class InputHiddenBean {
private boolean toggled1;
private boolean toggled2;
public void toggle1() {
this.toggled1 = !toggled1;
}
public void toggle2() {
this.toggled2 = !toggled2;
}
public void submit() {
addGlobalInfo("Submitted!");
}
public boolean isToggled1() {
return toggled1;
}
public void setToggled1(boolean toggled1) {
this.toggled1 = toggled1;
}
public boolean isToggled2() {
return toggled2;
}
public void setToggled2(boolean toggled2) {
this.toggled2 = toggled2;
}
}