JSF A4J: CommandButton não está funcionando quando 'desativado' está definido
Pergunta
Quando incluo um atributo 'desativado' em um A4J: CommandButton, a ação do botão não é executada. Tomar o atributo 'desativado' faz com que ele funcione corretamente. Não estou fazendo nenhuma validação especial (que estou ciente) e não estou vendo nenhuma mensagem de erro de validação.
Aqui está parte da minha página:
<t:dataTable id="myTable"
var="region"
value="#{MyPageBackingBean.regions}"
width="100%">
...
<a4j:commandButton value="Update"
action="#{region.doUpdate}"
oncomplete="alert('done');"
disabled="#{!empty region && region.messageEmpty}"
immediate="true"/>
...
</t:dataTable>
Alguma ideia? Obrigado!
Editar:
Tentei definir preservouvetAmodel = "true" no t: datatable sem sucesso.
Também fiz um teste com um A4J: CommandButton e Text Box sem tabela de dados, mas a ação do feijão de apoio ainda não está sendo demitida:
<h:form>
<a4j:region>
<a4j:outputPanel id="testregion">
<h:messages id="messages"/>
<a4j:status>
<f:facet name="start">
<h:graphicImage value="/images/progress_indicator.gif"/>
</f:facet>
</a4j:status>
<h:inputTextarea
rows="5"
value="#{MyPageBackingBean.myValue}"
style="width:100%; border: 1px solid #99CCFF;">
<a4j:support event="onkeyup"
reRender="testregion"
eventsQueue="messageModificationQueue"
ignoreDupResponses="true"
requestDelay="500"/>
</h:inputTextarea>
<a4j:commandButton id="doDelete"
value="Delete"
action="#{MyPageBackingBean.dummy}"
reRender="testregion"
disabled="#{empty MyPageBackingBean.myValue}"/>
<h:outputText value="#{MyPageBackingBean.myValue}"/>
</a4j:outputPanel>
</a4j:region>
</h:form>
Aqui está o novo código de feijão de apoio usado para testar:
private String m_myValue = null;
public String getMyValue()
{
return m_myValue;
}
public void setMyValue(String value)
{
m_myValue = value;
}
private String mystr2 = null;
public String dummy()
{
mystr2 = "hello";
return null;
}
Obrigado!
Solução
No mundo HTML, o disabled
atributo causa o name
-value
Par de atributo de qualquer elemento de entrada HTML (input
, select
, textarea
e button
) não sendo enviado para o lado do servidor.
No mundo JSF, a presença do name
O atributo é usado para identificar a ação do feijão a ser invocada no lado do servidor. No entanto, durante a fase de valores de solicitação de aplicação do formulário, envie o JSF também verifica se o componente do componente disabled
(e rendered
) Attribtue avalia true
antes de tomar alguma ação.
o #{region}
está aqui um objeto de linha de tabela iterado de #{MyPageBackingBean.regions}
de quem isMessageEmpty()
getter por devoluções padrão true
. Na nova solicitação do formulário, envie o #{MyPageBackingBean.regions}
está aparentemente vazio qual efetivamente faz o botão disabled
. A JSF não invocará a ação associada então.
Ao ponto, você precisa ter certeza de que #{MyPageBackingBean.regions}
Retorna exatamente o mesmo datamodel na solicitação subsequente. A correção mais fácil é colocar o MyPageBackingBean
Bean no escopo da sessão para que não seja reinicializado na solicitação subsequente, mas isso também tem mais efeitos colaterais negativos. Outra correção é reorganizar o carregamento do datamodel para que ocorra no construtor de feijões. Como você já está usando o Tomahawk <t:dataTable>
, você precisa definir seu preserveDataModel
atribuir a true
. Para obter mais dicas sobre o uso de Datatables, você também pode achar este artigo útil: Usando datatables.
Outras dicas
Outra coisa a observar sobre a propriedade desativada para um A4J: CommandButton: se a propriedade desativada estiver definida como true, o gancho Ajax para o evento OnClick do botão nunca será renderizado no HTML final. Isto é, você recebe um botão como este:
<input type="button" onclick="return false" ... />
em vez disso:
<input type="button" onclick="A4J.AJAX.Submit('....');return false" ... />
Então, se você quiser fazer algo assim:
- Renderize a página com o Botão A4J:
- Ativar A4J: Botão no lado do cliente com base na interação do usuário
- Clique em A4J: Botão para chamar a ação do lado do servidor
Então você precisará fazer algo assim:
- Renderize a página com A4J: Button e Disabled = "#{true}"
- Peça à interação do usuário que acione um renderizador do botão A4J: com desabiled = "#{false}"
- Clique no botão A4J: para chamar a ação do lado do servidor
Aqui está um exemplo simples:
<h:selectOneCheckbox value="#{myAction.booleanProperty}">
<a4j:support event="onclick" reRender="button1" />
</h:selectOneCheckbox>
<a4j:commandButton id="button1" action="#{myAction.doSomething}"
disabled="#{myAction.booleanProperty eq false}" value="click me"
/>