I previously discussed the JSF truism that you can’t re-render something you never rendered in the first place. Here's another one: You can't submit a disabled form element.

Here's the situation. We've got a form with a text input element that, by default, we want to be disabled unless the user changes something else, client-side, on the page. The obvious, intuitive way to do this is with the disabled attribute:

<h:inputText id="newId" value="#{thePage.newId}" disabled="true" />

Then, once the user initiates whatever action to enable the text input element, we use some JavaScript to twiddle the disabled attribute, thereby making it editable. However, if the user then fills out that text input element and submits the form, the backing bean won't receive the user-supplied value. Why? I can only surmise that, according to the JSF viewState, the text input element in question is still disabled. Therefore, JSF sees no point in processing text input element.

One efficient (but hacky and verbose) way around this is to always keep the text input element enabled from JSF's standpoint and, instead, do it all using JavaScript. The first step is to remove the disabled attribute from the text input element:

<h:inputText id="newId" value="#{thePage.newId}" />

Instead, we use jQuery to disable the text input element at page-load time:

jQuery(document).ready(function(){
    var newIdInput = jQuery("#theForm\:newId");
    newIdInput.attr({ disabled:true });
});

Some CSS styling completes the job, making the text input element actually "look" disabled in all browsers:

input#theForm3A newId
{
    background-color: #D6D6D6;
}
span#theForm3A newIdInputLabel
{
    color: #9C9C9C;
}

Finally, we add a JavaScript event handler function to twiddle the attribute value:

var handleSomeChange = function()
{
    var labelColor = "#9C9C9C";
    var inputColor = "#D6D6D6";
    var disabledSwitch = true;
    if ([test to see if newId should be enabled returns true])
    {
        labelColor = "#000000";
        inputColor = "#FFFFFF";
        disabledSwitch = false;
    }

    var newIdInputLabel =
        jQuery("#theForm\:newIdInputLabel");
    newIdInputLabel.css("color", labelColor);
    var newIdInput = jQuery("#theForm\:newId");
    newIdInput.attr({ disabled:disabledSwitch });
    newIdInput.css("backgroundColor", inputColor);
}

The more pure JSF way to get this done (using RichFaces) is to have the event handler function call the server, which would determine the proper disabled/enabled state and then reRender the text input element or containing form. In this way, the server-side viewState and client-side state remain in sync. But, in some instances, this introduces too much latency and negatively impacts usability. The option is available, though.

If you are, for example, disabling/enabling a text input element in a compact form in response to a checkbox being checked in that same form, I'd go with the client-side approach. However, if you are disabling/enabling lots of form elements in response to a button being clicked, going the server-side route might be more appropriate (from both a technical complexity and usability perspective).

I hope this helps.