AjaxStatus not working with dialog - ajax

I have a ajaxstatus and dialog which is used for searching
<h:body>
<p:ajaxStatus onstart="statusDialog.show();" onsuccess="statusDialog.hide();"/>
<p:dialog id="loading" modal="true" widgetVar="statusDialog" header="" draggable="false" closable="false">
<p:graphicImage value="/images/ajax-loader.gif" />
</p:dialog>
Dialog Part
<p:dialog id="showDial" header="Search" widgetVar="srch" resizable="false" >
<h:panelGrid id="searchGrid" columns="2" cellpadding="10" >
<h:outputLabel id="srchIdLbl" value="Employee ID:" />
<p:inputText id="srchIdTxt" value="#{employee.employeeId}" />
<p:commandButton id="search1" value="Search" type="submit" action ="#{employee.search()}"
update="patientTbl"/>
<p:commandButton id="reset1" value="Reset" type="reset" />
</h:panelGrid>
</p:dialog>
the above code works fine, it displays the loading dialog. But once the search is completed the dialog will remain in the screen.
I added the below code in the commandButton id="search1" to close the dialog
onComplete="showDialog.hide()"
*Problem:*If i add the above line the AjaxStatus is not shown. I want to know why its not displaying.
I also tried adding the below code to the commandButton id="search1"
onclick="statusDialog.show()" onselect="statusDialog.show()" onmousedown="statusDialog.show()" onComplete="showDialog.hide() statusDialog.hide()"
Problem In the above code the background to dialog is disabled until the ManagedBeans code is completed and the dialog also closes but when i click the search button it loads with the previously entered search parameter even on clicking the reset button the data doesn't go.
How do i overcome the above problem of the previously entered data not going or how can i do the Ajaxstatus in a better way to avoid the above problems.

Related

Validation errors in dialog not updating after failed submit in JSF

So I click a button which opens a dialog. Inside this dialog I want to fill out information in a form and submit and save it. Some of the inputTexts need to be required in order to submit. So I use the required="true" attribute. It stops the submission, but it does not update the field with a red outline of everything. Now, if I hit cancel and open up the dialog again it will show the fields that failed validation with a red outline!
I thought I could solve this by manually updating the dialog whenever I try to submit the form. This just causes the dialog to close though instead of staying open and refreshing the dialog to show the validation failures.
This is the dialog, when I hit the save button is when I submit the form
<h:form>
<p:dialog header="#{headerValue}" widgetVar="#{uniqueId}_editDialog"
modal="false" showEffect="fade" styleClass="dialogGrid"
dynamic="true" draggable="true" resizable="false">
<p:outputPanel style="text-align:center;" layout="block">
<p:messages autoUpdate="true"/>
<ui:insert name="editContent">
Edit Content Here. Use 'selectedModel.whatever'
</ui:insert>
<p:panelGrid columns="3" styleClass="buttonGrid">
<ui:insert name="saveButton">
<p:commandButton iconPos="left" value="#{msg.save}"
rendered="#{'VIEW' != selectedModel.viewState}"
process="#widgetVar(#{uniqueId}_editDialog)"
action="#{adapterInjector.add(modelList, selectedModel)}"
update="#widgetVar(#{uniqueId}_itemsDataList) #widgetVar(#{uniqueId}_addButton) #widgetVar(#{uniqueId}_editDialog)"
oncomplete="if(!args.validationFailed) PF('#{uniqueId}_editDialog').hide()"
partialSubmit="true" validateClient="true">
</p:commandButton>
</ui:insert>
<p:commandButton iconPos="right" value="#{msg.cancel}"
process="#this" oncomplete="PF('#{uniqueId}_editDialog').hide()"
resetValues="true" partialSubmit="true">
</p:commandButton>
</p:panelGrid>
</p:outputPanel>
</p:dialog>
</h:form>
This is an inserted component which has the required attribute
<p:selectOneMenu id="licenseCert"
value="#{selectedModel.selectedLicenseCert}" filter="true"
required="true">
<f:selectItem itemLabel="#{msg.selectOne}" itemValue=""
noSelectionOption="true" />
<f:selectItems value="#{licCert.allLicenseCertMap.entrySet()}"
var="entry" itemValue="#{entry.key}" itemLabel="#{entry.value}" />
</p:selectOneMenu>
</p:column>
Turns out this fixed the problem.
For best practice you should:
move the <h:form> inside the dialog
process the moved <h:form> in the save button.

Prevent confirmation dialogue from opening when there's a validation error

I have a text area inside a tab of accordion panel which is a description. I am trying to edit a description and saving it. I am validating the text area so that max character shouldn't exceed 1000 character. I am using <p:message> to display validation message. Before the actual save, a confirmation dialogue will be shown to confirm the save.
<p:messages showDetail="true" autoUpdate="true" />
<p:accordionPanel dynamic="true">
<p:tab id="_0" title="description">
<p:inputTextarea styleClass="max" id="editDesc1" widgetVar="txtBox" value="#{testBean.description}"
rows="6" cols="150" validatorMessage="#{msg.AddSystem_validationMsg5}" autoResize="false">
<f:validateLength maximum="1000"></f:validateLength>
</p:inputTextarea>
<p:commandButton value="save" oncomplete="saveDialog.show()"/>
<p:confirmDialog message="#{msg.EditSystem_confirmMsg1}" width="200"
showEffect="explode" hideEffect="explode"
header="Confirm" severity="alert" widgetVar="saveDialog">
<p:commandButton value="#{msg.EditSystem_confirmAnswer1}" action="#{testBean.saveEdit}" process="#this" />
<p:commandButton value="#{msg.EditSystem_confirmAnswer2}" onclick="saveDialog.hide()" type="button" />
If an user enters more than 1000 characters and tries to save it, then the validation message appears for a short time and then the confirmation dialogue pops up, causing the validation message to disappear. How do I prevent the confirmation dialogue from popping up when there is a validation error?
You need to check in oncomplete of the save button if validation hasn't failed. PrimeFaces puts a global args object in the JavaScript scope which in turn has a boolean validationFailed property. You could make use of it:
<p:commandButton value="save" oncomplete="if (args && !args.validationFailed) saveDialog.show()"/>
This way the confirm dialog will only be shown if the validation has not failed.
I think you can use javascript to validate:
<script type="text/javascript">
function test(){
// validation here
if(isValidated){saveDialog.show()}
else alert('exceed ...');
}
</script>
<p:commandButton value="save" onclick="test()"/>

richfaces select menu rendering triggered by event

I have popup window that is used in few tabs and popup uses some params from tabs such as dialogContainerId and dialogId.
I have "select item" menu and "refresh items" button near it. So when user click button i want to get new item list for select menu. Select menu works as expected, but "refresh" button is not. I'm sure that listener on refresh button works well and can see updated item list if new items appear in database. But select menu doesn't update. It seems like render attribute on f:ajax doesn't work or there is id mismatch. I checked page and found nothing. Ids look well. I tried constant ids, and tried to move id to parent tag, but always have got same result - select menu is not re-rendered.
Does any one have ideas or suggestions? Thanks in advance.
Here is source page:
<ui:composition>
<h:panelGroup id="#{dialogContainerId}">
<rich:popupPanel id="#{dialogId}" autosized="true" modal="true" domElementAttachment="parent">
<h:panelGrid id="#{dialogId}commonControls" columns="3">
<!-- more input tags -->
<h:outputLabel value="Create dialog" />
<h:panelGroup>
<rich:select id="#{dialogId}expenseItem" value="#{expenseItemInstanceBean.selectedExpenseItemId}"
selectFirst="true" required="true" requiredMessage="Required">
<f:selectItems value="#{expenseItemInstanceBean.expenseItemsAsList}"
var="item" itemValue="#{item.id}" itemLabel="#{item.name}" />
</rich:select>
<h:graphicImage library="icons" name="refresh_16x16.gif" title="Refresh">
<f:ajax event="click" execute="#this" render="#{dialogId}expenseItem"
listener="#{expenseItemInstanceBean.refreshExpenseItems()}" />
</h:graphicImage>
</h:panelGroup>
<h:messages for="#{dialogId}expenseItem" />
<!-- more input tags -->
</h:panelGrid>
<!-- button tags tags -->
</rich:popupPanel>
</h:panelGroup>
</ui:composition>
And part of rendered html page:
<td>
<div class="rf-sel" id="idForm:wrkSchedDialogexpenseItem">
<!-- here is my list and additional autogenerated jsf tags -->
</div>
<img id="idForm:j_idt42" src="/logistics-web/javax.faces.resource refresh_16x16.gif.xhtml?ln=icons"
alt="" style="vertical-align: bottom" title="Refresh"
onclick="mojarra.ab(this,event,'click','#this','idForm:wrkSchedDialogexpenseItem');return false"
class="linkLikeCursor" name="idForm:j_idt42"/>ev
</td>

Richfaces <a4j:ajax> and <rich:popupPanel> "conflict"

I've stumbled upon a strage behavior of richfaces. Some background about my view structure:
It's mainly a <rich:extendedDataTable> where a click on a row displays info about it on a <a4j:outputPanel>
Also, each row has a context menu with items like "Create", "Edit", etc... that pops a <rich:popupPanel>
The component structure is this:
<h:panelGrid columns="2">
<h:column>
<rich:dataScroller for="testTable" maxPages="7"/>
<rich:extendedDataTable id="testTable" value="#{testController.items}" rendered="#{testController.items.rowCount != 0}"
selection="#{testController.selectedRow}" noDataLabel="No results to show" var="test" rows="20"
style="width: 790px" selectionMode="single">
<a4j:ajax execute="#form"
event="selectionchange"
listener="#{testController.selectionListener}"
render=":res"/>
{columns to display}
</rich:extendedDataTable>
</h:column>
<a4j:outputPanel id="res">
<rich:panel header="Selected Rows:" rendered="#{not empty testController.selectedRows}">
<rich:list type="unordered" value="#{testController.selectedRows}" var="t">
<h:outputText value="#{t.name}"/>
<br/>
<h:outputText value="#{t.details}" converter="#{testConverter}"/>
</rich:list>
</rich:panel>
</a4j:outputPanel>
</h:panelGrid>
<rich:contextMenu target="testTable" mode="ajax" id="contextMenu">
<rich:menuItem label="Edit" render="popupEdit" oncomplete="#{rich:component('popupEdit')}.show();" mode="ajax"/>
</rich:contextMenu>
<rich:popupPanel id="popupEdit" modal="true" autosized="true" resizeable="false" moveable="false" domElementAttachment="form">
<rich:hotKey key="esc" onkeyup="#{rich:component('popupEdit')}.hide(); return false;"/>
<f:facet name="header">
<h:outputText value="Edit Test"/>
</f:facet>
<f:facet name="controls">
<h:outputLink value="#" onclick="#{rich:component('popupEditar')}.hide(); return false;">
<h:graphicImage value="/resources/css/images/fechar_janela.png" width="20" height="20"/>
</h:outputLink>
</f:facet>
<h:panelGrid id="popupEditContent" columns="2">
... {display of info}
<a4j:commandButton value="Salvar" actionListener="#{testeController.update()}" render="tabelaTestes, contextMenu"/>
<h:panelGroup id="messagePanel" layout="block">
<rich:messages ajaxRendered="true" />
</h:panelGroup>
</h:panelGrid>
</rich:popupPanel>
And now the strange behaviour (using NetBeans):
Deploy the app from NetBeans;
Open the URL of the deployed project on browser (Firefox) . The <a4j:ajax> inlined in the table doesn't work, I know this because the 'testController.selectionListener' is not called and the details are not displayed (it sets the attribute current in the backing bean). The contextMenu works but the popupPanel shows null or empty properties in all fields (the current attribute is not set);
Go back to the IDE, remove all the <rich:popupPanel> section and save the file;
Back in the browser, hit F5 and click a row. Now the <a4j:ajax> works and calls testController.selectionListener, showing the details in <a4j:outputPanel>. The context menu works but (obviously) the panel does not pop;
In the IDE, put back the <rich:popupPanel> section and save the file;
Now refresh the page again, and everything works, details are shown and the Edit pop up shows the right info of the selected row.
I have tried deploying it without the <rich:popupPanel> section and the selecionListener gets called. I think that the problem is deploying the page with both <a4j:ajax> and <rich:popupPanel> sections, hence the "conflict".
I took the structure from the richfaces showcase and made changes. I noticed that in the showcase, the <rich:popupPanel> is placed outside the <h:form> tag, wich in my project is placed in the template.xhtml (so a topmenu page works). Is it possible that the error is caused by this placement?
Could this be considered a bug to file in the richfaces project or am I missing something there?
Is there a workaround or solution?
Thank you very much!
I think I have solved it. I set the id attribute to "form" in the <h:form> tag, in template.xhtml, so now it looks like this:
<h:body>
<h:form id="form">
<div id="top" class="top">
<ui:insert name="top">Top</ui:insert>
</div>
<div id="content" class="center_content">
<ui:insert name="content">Content</ui:insert>
</div>
</h:form>
</h:body>
It was the only change I made and now all the components work at first post-deploy.
Edit: Found the solution when searching for another problem: JSF action call on secon click

How to skip validation on certain fields in JSF 2 when required

I have two p:dialog. Each one contains some input fields which are marked as required. Only one dialog is shown at a time but when I submit on any of the dialog, JSF also validates the input fields of the dialog which is not shown. What is the best approach to skip the validations in JSF 2 for the dialog which is not shown. One approach could be that I set the required="condation". But dont know what that condition could be and is it goin to work.
Each dialog is initially hidden. Each one has its own button to show. When one is active and I click the save button there is a validation error even when the required field has values. The validation error comes from the inactive dialog panel. May be it give some idea what i am trying to do.
UPDATE
<p:dialog header="Edit Group" widgetVar="dialog_groupEdit" resizable="false"
width="300" showEffect="bounce" hideEffect="explode" modal="true" position="center">
<h:panelGrid id="panel_groupEdit" columns="2">
<h:outputText value="Group Name: "/>
<h:inputText id="input_gnameEdit" size="26" value="#{groupBean.selectionGroup.gname}" required="true" requiredMessage="Edit Group: Name is required."/>
<h:outputText value="Description:"/>
<h:inputTextarea rows="6" cols="23" value="#{groupBean.selectionGroup.description}"/>
<div></div>
<p:commandButton value="Save" action="#{groupBean.saveGroupChanges}" oncomplete="#{args.validationFailed ? '':'dialog_groupEdit.hide()'}"
update="panel_groups panel_groupEdit" style="float:right;"/>
<div></div>
<p:message for="input_gnameEdit"/>
</h:panelGrid>
</p:dialog>
<p:dialog header="New Group" widgetVar="dialog_groupCreate" resizable="false"
width="300" showEffect="bounce" hideEffect="explode" modal="true" position="center">
<h:panelGrid id="panel_groupCreate" columns="2">
<h:outputText value="Group Name: "/>
<h:inputText id="input_gnameCreate" size="26" value="#{groupBean.createGroup.gname}" required="true" requiredMessage="New Group: Name is reqired."/>
<h:outputText value="Description:"/>
<h:inputTextarea rows="6" cols="23" value="#{groupBean.createGroup.description}"/>
<div></div>
<p:commandButton value="Save" actionListener="#{groupBean.saveGroupCreate}" oncomplete="#{empty groupBean.createGroup.gname ? ' ':'dialog_groupCreate.hide()'}"
update="panel_groupCreate panel_groups" style="float:right;"/>
<div></div>
<p:message for="input_gnameCreate"/>
</h:panelGrid>
</p:dialog>
One approach could be that I set the required="condation".
This is going to be clumsy. Just put each individual form in its own separate <h:form> component, or use the process attribute of the <p:commandButton> to identify the region you'd like to process.
<p:commandButton process="panel_groupEdit" ... />
...
<p:commandButton process="panel_groupCreate" ... />
Having a "God" form is in any way a poor practice.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
How to use <h:form> in JSF page? Single form? Multiple forms? Nested forms?
When you are using <p:dialog some of the good practices as advised on the PF forum are -
Never put your <p:dialog inside any other component. Place it somewhere so that it falls right under the <h:body.
Give every <p:dialog it's own form. But, don't place the dialog inside the form, place the form inside the dialog. It's not good to update the dialog itself, only it's content. (I think this should solve your issue also.)
e.g.
<p:dialog widgetVar="dlg" ...
<h:form ...
<h:panelGroup id="dlgContent" ...

Resources