quarta-feira, 25 de março de 2009

Persistindo o estado do Richfaces panelMenuGroup com dojo e javascript

Persistindo o estado da Richfaces Group Menus

PROBLEMA: Quando a página entra página os menuItems ficam escondidos em seus grupos, entao o usuario clica no grupo de menu e entao os menuItems aparecem. Então o usuário clica em um dos menus e o jsf faz a nevegação para a página que a action do menu solicita. Quando a response do request chega de volta ao browser o menu aparece de novo porém os menuItems que estavam aberto agora estão escondidos de novo. Ou seja, ele sempre aparece do mesmo jeito. Portanto, o seu estado, ou seja, quais menuItems que eram visíveis e os que não eram, não fica guardado em lugar nenhum para que voltem a aparecer igualzinho no momento em que estava antes da requisição.

SOLUÇÃO: estou postando aqui uma alternativa. Talvêz nem seja a melhor, mas funciona. Para persistir o estado eu coloquei um inputHidden que guarda a propriedade css display do menuItem (que na verdade é um DIV).


Explicação detalhada:

Quando você coloca isso no JSP ou no seu XHTML ....

< label="GrupoDeMenus1">
< rich:panelMenuItem
id="menuItem1_DoGrupoDeMenu1"
label="menuItem1_Label"
action="SuporteSocial" < ! -- no meu caso, o jsf naveja para a pagina de suporte social -->
ajapxSingle="true" onclick="persistState()"/>

< rich:panelMenuItem id="menuItem_PercepcaoSaude"
label="Percepção Saúde"
action="PercepcaoSaude"
ajapxSingle="false" onclick="persistState()"/>
< /rich:panelMenuGroup>

o JSF renderiza isso como html para o browser...
< id="form:j_id22" class="dr-pmenu-top-group-div rich-pmenu-top-group-div">
< id="tablehideform:j_id22" class="dr-pmenu-top-group rich-pmenu-top-group rich-pmenu-group" cellspacing="0" cellpadding="0" border="0" style="">
<>
< id="row_form:j_id22" class="dr-pmenu-selected-item rich-pmenu-selected-element">
< class="dr-pmenu-nowrap rich-pmenu-group-self-icon">
< id="leftIconform:j_id22" width="16" vspace="0" hspace="0" height="16" alt=" " src="/reatreamentov2/a4j/g/3_3_0.GAorg.richfaces.renderkit.html.iconimages.PanelMenuIconSpacer/DATB/eAFjYGAAAAADAAE_">
< /td>
< id="iconform:j_id22" class="dr-pmenu-group-self-label rich-pmenu-group-self-label rich-pmenu-top-group-self-label" style="width: 100%;">
< /td>
< class="rich-pmenu-group-self-icon rich-pmenu-top-group-self-icon">
< /td>
< /tr>
< /tbody>
< /table>
< id="form:menuItem_SuporteSocial" style="">
< id="tablehideform:menuItem_SuporteSocial" class="dr-pmenu-item rich-pmenu-item" cellspacing="0" cellpadding="0" border="0" onclick="persistState()" style="">
<>
< id="row_form:menuItem_SuporteSocial" class="">
< class="dr-pmenu-nowrap rich-pmenu-item-icon">
< /td>
< id="iconform:menuItem_SuporteSocial" class="dr-pmenu-group-self-label rich-pmenu-item-label" style="width: 100%;">
< /td>
<>
< /td>
< /tr>
< /tbody>
< /table>
< /div>
< id="form:menuItem_PercepcaoSaude" style="">
< /div>
< id="form:menuItem_Comorbidades" style="">
< id="tablehideform:menuItem_Comorbidades" class="dr-pmenu-item rich-pmenu-item" cellspacing="0" cellpadding="0" border="0" onclick="persistState()" style="">
<>
< id="row_form:menuItem_Comorbidades" class="">
< class="dr-pmenu-nowrap rich-pmenu-item-icon">
< /td>
< id="iconform:menuItem_Comorbidades" class="dr-pmenu-group-self-label rich-pmenu-item-label" style="width: 100%;">
< /td>
<>
< /td>
< /tr>
< /tbody>
< /table>
< /div>
< id="form:menuItem_NumMedicamentos" style="">
< /div>
< id="form:menuItem_NumInternacoes" style="">
< /div>
< /div>



Com um pouco de paciência e como firebug você vai perceber que o menuItem, que agente quer guardar o estado dele ( ou seja, queremos que se ele estivesse aparecendo antes da requisição ele esteja aparecendo também depois que o response da requisição terminar) é simplemente os seguintes divs:


< id="form:menuItem_SuporteSocial" style="">
< id="tablehideform:menuItem_SuporteSocial" class="dr-pmenu-item rich-pmenu-item" cellspacing="0" cellpadding="0" border="0" onclick="persistState()" style="">
<>
< id="row_form:menuItem_SuporteSocial" class="">
< class="dr-pmenu-nowrap rich-pmenu-item-icon">
< width="16" vspace="0" hspace="0" height="16" alt=" " src="/reatreamentov2/a4j/g/3_3_0.GAorg.richfaces.renderkit.html.iconimages.PanelMenuIconSpacer/DATB/eAH7cW0fAAVVAo0_">
< id="leftIconform:menuItem_SuporteSocial" width="16" vspace="0" hspace="0" height="16" alt=" " src="/reatreamentov2/a4j/g/3_3_0.GAorg.richfaces.renderkit.html.iconimages.PanelMenuIconGrid/DATB/eAH7cW0fAAVVAo0_">
< /td>
< id="iconform:menuItem_SuporteSocial" class="dr-pmenu-group-self-label rich-pmenu-item-label" style="width: 100%;">
< /td>
<>
< /td>
< /tr>
< /tbody>
< /table>
< /div>
< id="form:menuItem_PercepcaoSaude" style="">
< id="tablehideform:menuItem_PercepcaoSaude" class="dr-pmenu-item rich-pmenu-item" cellspacing="0" cellpadding="0" border="0" onclick="persistState()" style="">
<>
< id="row_form:menuItem_PercepcaoSaude" class="">
< class="dr-pmenu-nowrap rich-pmenu-item-icon">
< /td>
< id="iconform:menuItem_PercepcaoSaude" class="dr-pmenu-group-self-label rich-pmenu-item-label" style="width: 100%;">
< /td>
<>
< /td>
< /tr>
< /tbody>
< /table>
< /div>

Então, controlando a propriedade css display desses divs, controlamos também o estado de visualização deles;
Então o que eu fiz foi somente, no momento do clique, ou seja, momento em que vai começar a requisição, foi "pegar" esses divs via javascript, verificar a propriedade css diplay e guardar como texto no inputHideen. Depois quando a página aparece de novo, eu leio o inputHiddem e aplico nos divs de novo para atualizar o estado atual como o anterior.


É só carregar o escript na sua página;

dojo.require("dojox.json.ref");
function alertToTest(){
alert("panelMenuStateSuport.js carregado com sucesso !!!");
}


function persistState(){
alert("Persistindo o estado do menu... function persistState(){...")
var InputHidden_menuStateJsonObject = dojo.byId("form:InputHidden_menuStateJsonObject");

//menuItemQueSeraoPersistidos e seus estatdos
var menuItem_SuporteSocial = dojo.byId("form:menuItem_SuporteSocial");
var menuItem_SuporteSocial_state = dojo.style(menuItem_SuporteSocial, "display");

var menuItem_PercepcaoSaude = dojo.byId("form:menuItem_PercepcaoSaude");
var menuItem_PercepcaoSaude_state = dojo.style(menuItem_PercepcaoSaude, "display");


//contruindo o objeto string a ser persistindo (antes de persistir)
var state = {
menuItem_SuporteSocial : menuItem_SuporteSocial_state,
menuItem_PercepcaoSaude : menuItem_PercepcaoSaude_state
};


var state_str = dojo.toJson(state);
dojo.attr(InputHidden_menuStateJsonObject, "value", state_str);

}


function updateMenuItemsWithThe_PersistedState(){
//alert("atualizando menu atraves do estado persistido da req anterior : function updateMenuItemsWithThe_PersistedState(){...");


//========================= recuperando estado...
var InputHidden_menuStateJsonObject = dojo.byId("form:InputHidden_menuStateJsonObject");
var state_JsonRecovered = InputHidden_menuStateJsonObject.value;
if (state_JsonRecovered == null){
return;
}//nao tem nenhum estado persistido nao temos que fazer nada em relacao a atualizar o menu
var state_ObjRecovered = dojo.fromJson(state_JsonRecovered);


//========================= aplicando, ou seja, atualizando o menu, com o estado recup...
var menuItem_SuporteSocial = dojo.byId("form:menuItem_SuporteSocial");
var menuItem_PercepcaoSaude = dojo.byId("form:menuItem_PercepcaoSaude");

dojo.style(menuItem_SuporteSocial, "display", state_ObjRecovered.menuItem_SuporteSocial);
dojo.style(menuItem_PercepcaoSaude, "display", state_ObjRecovered.menuItem_PercepcaoSaude);

}

Lembrando que o inputHidden tem que estar associado a algum field de um managedBean do jsf, Action do Struts ou alguma forma que viabilize devolver o valor dele com o response da request. No meu caso...
value="#{PanelMenuItemAction.statePersisted}"
id="InputHidden_menuStateJsonObject"/>


Bom, é isso. Tá muito direto, sem passo a passo sem estilo howto, mas se for o caso de interessar a alguem pode me enviar um email ou postar um comentário que eu detalho.
wagnerdocri@gmail.com
t+

Nenhum comentário: