Displaying a message from managed bean with primefaces confirmation dialog component - jsf-2

in my page , i'm trying to display a confirmation dialog after clicking a button .In the confirmation dialog i used the attribute message to display it , this message is taken value after clicking the button . So i did it like that :
<p:commandButton value="Delete" update="testPlanetree" id="deleteBtn"
disabled="#{projectTestManagementMB.disable}" oncomplete="deleteConfirmation.show()"
action="#{projectTestManagementMB.testFn}"/>
<p:confirmDialog id="confirmDialog" message="#
{projectTestManagementMB.deleteConfirmationMsg}"
header="Confirming Deleting Process" severity="alert"
widgetVar="deleteConfirmation">
<p:commandButton id="confirm" value="Yes Sure" update="messages"
oncomplete="deleteConfirmation.hide()" />
<p:commandButton id="decline" value="Not Yet"
onclick="deleteConfirmation.hide()" type="button" />
</p:confirmDialog>
ProjectTestManagementMB Managed Bean :
private String deleteConfirmationMsg;//with getters and setters
public void testFn(){
deleteConfirmationMsg="do you want to delete ...";
}
The problem is that the deleteConfirmationMsg never take the value "do you want to delete ..." (is always empty)
Any idea will be appreciated

The <p:confirmDialog> has already generated its HTML representation on the very first HTTP request returning the page with the form and the dialog. It's merely hidden by CSS and is supposed to be shown/hidden by JS. When you change the confirm message afterwards in a bean action method, then it won't be reflected in the generated HTML output as long as you don't ajax-update it.
So, in order to get the changed message being reflected, you'd need to update the HTML representation of the <p:confirmDialog> in the client side before showing it in the oncomplete. You can for this use the update attribute of the command button which should show the dialog.
<p:commandButton ... update="confirmDialog testPlanetree">

try this i should works :
<p:commandButton value="Delete" update="testPlanetree" id="deleteBtn" actionListener="#
{projectTestManagementMB.testFn}"
disabled="# {projectTestManagementMB.disable}"
oncomplete="deleteConfirmation.show()" />

Related

Primefaces 5.1 Dialog Framework dialogReturn event handler not called

I'm new to JSF and primefaces. I'm using the Primefaces Dialog Framework to pop a modal terms of service agreement. The problem I'm having is that my dialogReturn event handler is not invoked when the dialog closes and the modal overlay remains on the page although the dialog itself closes. The modal overlay may be a red herring because the dialogReturn method is not invoked when the dialog is not modal either.
Here are the relevant pieces of code:
The form from which the dialog is created:
<h:form prependId="false">
<ul>
<ui:repeat value="#{serviceEditor.service.subsystems}" var="ss">
<li>
<em>#{ss.name}</em> - #{ss.description}<br/>
<ui:fragment rendered="#{identity.loggedIn}">
<ui:fragment rendered="#{grantManager.hasAccess(ss)}">
(You have access to this dataset.)
<h:commandButton value="Discontinue Access" action="#{grantManager.unrequestAccess(ss)}"/>
</ui:fragment>
<ui:fragment rendered="#{!grantManager.hasAccess(ss)}">
<p:commandButton value="Request Access"
actionListener="#{serviceDialog.display(ss)}"
styleClass="btn btn-primary" >
<p:ajax event="dialogReturn"
listener="#{serviceEditor.acceptDialogHandler}" />
</p:commandButton>
</ui:fragment>
...
ServiceEditor is annotated #Named #Stateful #ConversationScoped
The actionListener code for the dialog display:
public void display (ServiceSubsystem sub)
{
if (sub == null)
{
log.error("Service Accept dialog attempt with null subservice. Lose.");
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Subservice Unavailable", "We seem to have misplaced that service. This has been logged for investigation.");
RequestContext.getCurrentInstance().showMessageInDialog(message);
return;
}
log.info("svcDlg: Displaying accept dialog for service: {}.{}", sub.getService().getName(), sub.getName());
this.sub = sub;
Map<String, Object> dlgOpts = new HashMap<>(2);
dlgOpts.put("modal", true);
RequestContext.getCurrentInstance().openDialog("serviceAcceptDialog", dlgOpts, null);
log.info("svcDlg: Did that accept dialog work out?");
}
The actionListener code for the accept command button in the dialog:
public void accept ()
{
log.info("Accepted {}.{}", sub.getService().getName(), sub.getName());
...
String destination = "/service?faces-redirect=true&uuid=" + sub.getService().getUuid();
log.info("Sending user to: {}", destination);
RequestContext.getCurrentInstance().closeDialog(destination);
}
And finally the dialog return listener that is not invoked:
public void acceptDialogHandler (SelectEvent event)
{
String dest = (String) event.getObject();
log.info("Service accept dialog closed. sending here: ", dest);
((ConfigurableNavigationHandler) FacesContext.getCurrentInstance().getApplication().getNavigationHandler())
.performNavigation(dest);
}
What did I miss in the documentation? Or is this a bug?
I think you can try to use primefaces dialog component, is simpler.
To show or close the dialog you only need to invoke it:
PF('widgetVarDialogName').hide();
PF('widgetVarDialogName').show();
You can open or close it in view actions, for example:
<p:commandButton
value="Open dialog"
type="button"
onclick="PF('widgetVarDialogName').show()" />
<p:commandButton
value="Do Action"
action="#{myBean.myAction()}"
oncomplete="PF('widgetVarDialogName').hide();" />
Also, you can invoke it from the bean if you want.
RequestContext.getCurrentInstance().execute("PF('widgetVarDialogName').show()");
RequestContext.getCurrentInstance().execute("PF('widgetVarDialogName').hide()");
(Remember, the dialog must be placed inside the form)
I see you work a lot with the rendered="..." attribute. From what I experienced the <p:ajax event="dialogReturn" /> is not getting fired if itself or a parent element is not rendered.
So have a look in your public void accept() method. If you change some state so that a rendered attirbute of a parent element of the <p:ajax event="dialogReturn" /> namely rendered="#{!grantManager.hasAccess(ss)}" and/or rendered="#{identity.loggedIn}" would evaluate to false then the listener would not be executed.
EDIT
A workaround just came to my mind. One can avoid the problem with the same workaround as if you want to trigger dialog framework from a <p:menuitem /> (Primefaces Dialog Framework — dialogReturn event from menuitem).
Simply create a separate button somewhere outside of the possibly not rendered area and trigger it via javascript.
Not tested code example:
<ui:fragment
id="fragment"
rendered="#{...}">
<h:commandButton
id="pseudo_button"
value="..."
onclick="document.getElementById('real_button').click()" />
</ui:fragment>
<h:commandButton
id="real_button"
action="#{bean.realWorkHere()}"
update="fragment"
style="display:none;">
<p:ajax
event="dialogReturn"
listener="#{...}" />
</h:commandButton>

show confirmDialog before rowEditor updates the model

I'm using PrimeFaces dataTable and rowEditor in pretty default way:
<p:dataTable id="payments-table" var="apayment" value="#{payment.payments}" editable="true">
<p:ajax event="rowEdit" listener="#{payment.update}"/>
...
</p:dataTable>
I'd like a confirmation dialog to show itself on clicking to the 'check' button of rowEditor.
I know it's possible using JS confirm function (thanks to Show a confirm message before <p:rowEditor> updates the model on click of "OK" button):
<p:ajax event="rowEdit" listener="#{payment.update}" onstart="return confirm('Save changes?')"/>
But I would like the dialog to conform to the UI theme, confirmDialog component being the best candidate. Alas, I don't know how to use it here. I tried the following and it won't work (simply no confirmation occurres):
<p:ajax event="rowEdit" listener="#{payment.update}">
<p:confirm header="Remove payment" message="Remove payment?" icon="ui-icon-trash"/>
</p:ajax>
....
<p:confirmDialog global="true">
<h:form id="form-payment-confirm">
<p:commandButton value="Yes" type="button" styleClass="ui-confirmdialog-yes" icon="ui-icon-check"/>
<p:commandButton value="No" type="button" styleClass="ui-confirmdialog-no" icon="ui-icon-close"/>
</h:form>
</p:confirmDialog>
Any ideas?
I think you can use in this case simple widgetVar and call show() or hide() functions. Here is your modified code:
<p:ajax event="rowEdit" listener="#{tableBean.onRowEdit}" oncomplete="myDialog.show()"/>
I use PF 3.5 and can't find global parameter in p:confirmDialog. May be it is new feature. So I simple deleted it of my code. Here is modified confirmDialog:
<p:confirmDialog widgetVar="myDialog" closeOnEscape="true" appendToBody="true" closable="true">
<h:form id="form-payment-confirm">
<p:commandButton value="Yes" type="button" update="#form" styleClass="ui-confirmdialog-yes" icon="ui-icon-check"/>
<p:commandButton value="No" type="button" onclick="myDialog.hide()" styleClass="ui-confirmdialog-no" icon="ui-icon-close"/>
</h:form>
</p:confirmDialog>
Please try and adjust this confirm dialog code! May be unnecessary code for update form or hide()...
EDIT:
If you want to dynamically adjust text message of confirmDialog, you can adjust from server-side. Perhaps it is not best solution. I think the second way is it adjust from client-side by JQuery.
Server-side:
The ajax event is same. It call onRowEdit listener which adjust simple String attribute. For example the bean containt:
String myDialogMessage = "Default message";
//getter and setter
public void onRowEdit(RowEditEvent event) {
myDialogMessage="Are you sure?";
}
and the dialog containt message property:
<p:confirmDialog widgetVar="myDialog" closeOnEscape="true" appendToBody="true" closable="true" message="{tableBean.myDialogMessage}">
Client-side:
You can use repleaceWith function of JQuery:
<script>
jQuery("myDialog.p").replaceWith(....
</script>
Of course need to develop more business logic to client-side, more functions. Maybe the server-side solution is faster.
Please try it!
Based on your comment, I edited:
I find this in 4.0 user' guide:
When pencil icon is clicked, row is displayed in editable mode meaning
input facets are displayed and output facets are hidden. Clicking
tick icon only saves that particular row and cancel icon reverts the
changes, both options are implemented with ajax interaction. Another
option for incell editing is cell editing, in this mode a cell
switches to edit mode when it is clicked, losing focus triggers an
ajax event to save the change value.
So ajax event works when row is change. Here is dataTable events which can you catch:
I hope this answer help to you find solution!

Update component after file download

I'm using Primefaces TabView, CommandButton and FileDownload to download a log file. Once the log file has been downloaded, I want to offer the option to delete the contents of the log from the server.
Initially the Delete Log File Button (deleteEventLogButton) is disabled and has a custom caption stating "Delete Logs - Export Required". Once the log has been exported, the button should be enabled and the caption should state "Delete Logs".
The problem that I'm having is that the Delete Log File Button is still disabled and the caption reads "Delete Logs - Export Required" even after the Export event completes successfully.
My guess is that the exportEventLogButton->Update="deleteEventLogButton" is being called before the fileDownload value.
Once I've exported the logs, I can hit 'F5' and refresh the page and the deleteEventLogButton is enabled showing the correct caption.
JSF - Snippet
<p:tabView id="logView">
<p:tab id="eventLogTab" title="Security Events">
<p:panelGrid ...>
<p:commandButton id="exportEventLogButton" icon="ui-icon-disk" styleClass="c25" ajax="false" title="Export Log" disabled="#{empty managedCmsLogsBean.eventLogEntityList}" update="deleteEventLogButton">
<p:fileDownload value="#{managedCmsLogsBean.exportEventLogFiles()}"/>
</p:commandButton>
<p:commandButton id="deleteEventLogButton" icon="ui-icon-trash" styleClass="c25" ajax="false" title="#{managedCmsLogsBean.deleteEventLogCaption}" disabled="#{! managedCmsLogsBean.eventLogExported}" action="#{managedCmsLogsBean.clearEventLogs()}" update="eventLogTab" />
</p:panelGrid>
<p:dataTable value="#{managedCmsLogsBean.eventLogEntityList}" ...>
...
</p:dataTable>
</p:tab>
</p:tabView>
Backing Bean - Snippet
private boolean eventLogExported;
public StreamedContent exportEventLogFiles() {
eventLogExported = true;
return logFileUtility.exportSecurityEventLog(eventLogEntityList, eventLogStartDate, eventLogStopDate);
}
public boolean isEventLogExported() {
return eventLogExported;
}
public void setEventLogExported(boolean value) {
eventLogExported = value;
}
public String getDeleteEventLogCaption() {
return eventLogExported ? "Delete Logs" : "Delete Logs - Export Required";
}
I tried moving the update event inside the FileDownload, but it didn't make a difference.
<p:commandButton id="exportEventLogButton" icon="ui-icon-disk" styleClass="c25" ajax="false" title="Export Log" disabled="#{empty managedCmsLogsBean.eventLogEntityList}">
<p:fileDownload value="#{managedCmsLogsBean.exportEventLogFiles()}">
<p:ajax update="deleteEventLogButton"/>
</p:fileDownload>
</p:commandButton>
I've searched for a couple of days now and have found MANY problems that come very close to this one... but none that have helped. :(
Just to make things very clear... I am NOT having problems with the export. The problem is that the Delete Log File Button is not enabled after the export is complete.
p:commandButton in your case is (an has to be) non-AJAX button (you set this by adding ajax="false" attribute). In that case update attribute and p:ajax tag doesn't have any sense (as they are only for AJAX requests). When you have file download your application sends streaming of some type, and you see Save File dialog. Your page is not refreshed. So you have to use PrimeFaces.monitorDownload to do this:
<p:commandButton id="exportEventLogButton"
icon="ui-icon-disk"
styleClass="c25"
ajax="false"
title="Export Log"
disabled="#{empty managedCmsLogsBean.eventLogEntityList}"
onclick="PrimeFaces.monitorDownload(null, stop)">
and add stop function which will update second button:
<p:remoteCommand name="stop" update="deleteEventLogButton"/>
As Balusc answered, In question (revisions) , we cannot get response twice from a single request, to refresh a page after download, better use the following java script in download link(p:commandbutton) onclick tag.
Example:
<p:commandButton ajax="false" icon="ui-icon-arrowstop-1-s" onclick="setTimeout('location.reload();', 1000);" action="#{managedBean.downloadMethod}" />
this will automatically refresh the page after 1 second, at the same time i.e. before refresh, you will get the download file, based on your download response time, increase the seconds in that script. Seconds should not less than that download response time.
From PrimeFaces 10, you are able to download files with ajax="true". This allows you to update components as well.
See also:
https://primefaces.github.io/primefaces/10_0_0/#/components/filedownload?id=ajax-downloading
https://github.com/primefaces/primefaces/issues/5978
Have you tried changing eventLogExported/isEventLogExported from boolean to Boolean or String ?

How to hide and show p:panel on commandbutton click

i have the following problem:
I'm new to JSF2 and primefaces.
I have a table in a page that will be populated with information, after the user enters a string and clicks a CommandButton. After clicking the button, I want it to be disabled until processing is over.
To disable the CommandButton I'm doing the following;
<p:commandButton update=":outPanel" widgetVar="btnSend" id="btnsend"
value="Calcular" actionListener="#{calcBean.getTrfs}"
onclick="btnSend.disable()" oncomplete="btnSend.enable()" />
And then I have a panel where I want to show its contents:
<p:panel id="outPanel" widgetVar="outpanel">
#{calcBean.result}
</p:panel>
How can I hide this outpanel when the page loads the first time?
How can I hide it when I click the CommandButton, and only show it again if the processing in my bean is successful?
Thanks.
Solved,
i have to put
closable="true" toggleable="true"
attributes in p:panel... Thanks
I have checked following panel hide and show using p:commandButton in JSF,
please try following methods in JSF,
<p:panel id="button_panel" widgetVar="testPanel" closable="true" toggleable="true">
<h1>Testing</h1>
</p:panel>
<p:commandButton onclick="PF('testPanel').show()" value="Show Panel" type="button"/>
<p:commandButton onclick="PF('testPanel').hide();" value="Hide Panel" type="button"/>
to show the panel after the ajax request is finished try this:
<p:commandButton update=":outPanel" widgetVar="btnSend" id="btnsend"
value="Calcular" actionListener="#{calcBean.getTrfs}"
onclick="btnSend.disable()" oncomplete="btnSend.enable();outPanel.show();" />

Why does my s:selectItems throws no such element exception?

I'm getting this error java.util.NoSuchElementException when i tried to check one of my checkbox under h:selectManycheckBox when i submit the form.
The many checkbox is dynamically populated from the bean. Here is my code.
<h:form id="eF">
<h:inputText id="i" value="#{aklat.suggest}">
<a4j:support event="onkeyup" action="#{aklat.complete}" reRender="m"></a4j:support>
</h:inputText>
<s:div>
<h:selectManyCheckbox value="#{aklat.selectedBooks}" layout="pageDirection" id="m">
<s:selectItems value="#{aklat.books}" var="_book" itemLabel="#{_book}" itemValue="#{_book}" label="#{_book.bookName}"/>
</h:selectManyCheckbox>
<a4j:commandButton value="Add Users" action="#{aklat.fire}"></a4j:commandButton>
</s:div>
</h:form>
The weird part is it renders some data output but when i checked the source code. there are no input type checkbox element.
Is something I am missing.
I assume your managed bean is request scope...
because you are making an ajax request, you have to enable "aklat.books" to persist its value longer than request but shorther than session scope.
If you have tomahawk between your app libraries you can use savestate like this (put it after the h:form tag) :
<t:saveState value="#{aklat.books}"/>
if no tomahawk, you can use a4j:keepAlive:
<a4j:keepAlive beanName = "#{aklat.books}"/>

Resources