You need to toggle it via server side, not via client side. JSF as being a stateful component based MVC framework safeguards this way against tampered/hacked requests wherein the enduser uses client side languages/tools like HTML or JS to manipulate the HTML DOM tree and/or HTTP request parameters in such way that the outcome of JSF's disabled
, readonly
or even rendered
attribute is altered.
Imagine what would happen if the JSF developer checked an user's role in such a boolean attribute against the admin role like so disabled="#{not user.hasRole('ADMIN')}"
and a hacker manipulated it in such way that it isn't disabled anymore for non-admin users. That's exactly why you can only change the mentioned attributes (and the required
attribute and all converters, validators, event listeners, etc) via the server side.
You can use <f:ajax>
in any ClientBehaviorHolder
component to achieve the requirement. You can let JSF generate a HTML <div>
via <h:panelGroup layout="block">
, which is also a ClientBehaviorHolder
:
<h:form>
<h:panelGroup layout="block">
Click this div to toggle the input.
<f:ajax event="click" listener="#{bean.toggle}" render="input" />
</h:panelGroup>
<h:inputText id="input" ... disabled="#{not bean.enabled}" />
</h:form>
With this @ViewScoped
managed bean (@RequestScoped
wouldn't work for reasons mentioned in #5 of commandButton/commandLink/ajax action/listener method not invoked or input value not updated):
@Named
@ViewScoped
public class Bean implements Serializable {
private boolean enabled;
public void toggle() {
enabled = !enabled;
}
public boolean isEnabled() {
return enabled;
}
}
See also:
Unrelated to the concrete problem, head to the following answers in case you're actually interested in how to obtain the HTML representation of JSF components via JS/jQuery: