JSF inputSwitch with confirmDialog - jsf

I have a inputSwitch that need to show a dialog to confirm or not the operation. The dialog should show a variable message if i put it on or off.
I do the next thing but the problem is when i push no and i toggle the switch to let in then original state it call the ajax event again and open the dialog again. How can i lauch the event only when i click and not when i call the .toggle function?
<p:outputLabel for="activa"
value="#{bundleBean.getValue('activa')}" />
<p:inputSwitch id="activa"
value="#{gestionBean.domainEntity.activa}" onLabel="Si"
offLabel="No"
widgetVar="switch#{gestionBean.domainEntity.id}">
<p:ajax event="change" update="test" oncomplete="PF('dialog#{gestionBean.domainEntity.id}').show()"></p:ajax>
</p:inputSwitch>
<div>
<p:confirmDialog id="test"
widgetVar="dialog#{gestionBean.domainEntity.id}"
styleClass="content-confirmation-dialog"
message="#{gestionBean.mensajeDialogoActiva(gestionBean.domainEntity.activa)}"
header="#{bundleBean.getValue('confirmacion')}" closable="false">
<p:commandButton value="Si"
styleClass="boton rounded-button ui-button-danger float-right ui-confirmdialog-yes" immediate="true"
onclick="PF('dialog#{gestionBean.domainEntity.id}').hide()" />
<!-- action="#{gestionBean.cambiarEstado(gestionBean.domainEntity)}" -->
<p:commandButton value="No" styleClass="boton rounded-button ui-button ui-confirmdialog-no"
immediate="true"
update="activa"
onclick="PF('switch#{gestionBean.domainEntity.id}').toggle(); PF('dialog#{gestionBean.domainEntity.id}').hide()" />
</p:confirmDialog>

You can update the form, instead of the switch, when you click the No button and the dialog will not be shown.
<p:commandButton update="#from">

An alternative approach to solve this problem is to do away with the p:confirmDialog and instead have the change event on the p:inputSwitch / p:toggleSwitch trigger a click event on a hidden commandButton. For example:
<p:inputSwitch id="toggle" value="#{toggleSwitchController.toggleOn}" >
<p:ajax oncomplete="PF('hidnBtn').getJQ().click();"/>
</p:inputSwitch>
<p:commandButton id="hiddenBtn" widgetVar="hidnBtn"
action="#{toggleSwitchController.toggleChanged}"
style="visibility: hidden;">
<p:ajax event="dialogReturn" update=":frm1:growl toggle"
listener="#{toggleSwitchController.handleReturn}" />
</p:commandButton>
The action that the hidden p:commandButton calls can test the value of the toggle and if set to true/yes use PrimeFace's dialog framework to show a confirmation dialog. The dialog can return a boolean, which can be tested in the handleReturn function.
public void toggleChanged() {
if (toggleOn) {
Map<String, Object> options = new HashMap<>();
options.put("resizable", false);
options.put("draggable", false);
options.put("closable", false);
options.put("modal", true);
PrimeFaces.current().dialog().openDynamic("/pages/pleaseConfirm", options, null);
}
}
public void handleReturn(SelectEvent<Boolean> event) {
boolean confirmed = event.getObject();
if (confirmed) {
facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "confirmed", null));
} else {
facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "not confirmed", null));
toggleOn = false;
}
}
You could make the "pleaseConfirm" dialog more reusable by providing parameters for the text strings through the openDynamic() call.

The problem can be solved by adding a listener to the ajax change event, making the listener return the current value of the toggle and testing the returned value in the onComplete clause before showing the dialog.
<p:inputSwitch id="activa"
value="#{toggleSwitchController.toggleOn}"
onLabel="Si" offLabel="No"
widgetVar="toggleWidget" >
<p:ajax event="change"
listener="#{toggleSwitchController.testToggle}"
update="test"
oncomplete="if ( args.toggleValue == 1 ) { PF('dlgWidget').show();}" />
</p:inputSwitch>
The listener can be very simple:
public void testToggle() {
PrimeFaces.current().ajax().addCallbackParam("toggleValue", (toggleOn ? 1 : 0));
}

Related

Each row in DataTable has checkboxes .How to uncheck the previous checked box, on check of new checkbox

On click of Add button, empty row with text box and check box is created. I have to enter the details in text box but only one checkbox should be checked. Now I can check all the check boxes. But if one is checked, other check boxes should be unchecked.
<p:commandButton value="Add"
actionListener="#{createReturns.addReturnBodyToList}" ajax="true"
update="bodyTable messages" style="margin-bottom:10px;"/>
<p:dataTable id="bodyTable" value="#{createReturns.returnBodyList}"
var="returnBody">
<p:column headerText="Element Name" style="width:250px;">
<p:inputText id="elementName" value="#{returnBody.elementName}"
style="width:240px;" />
</p:column>
<p:column headerText="KeyColumn" style="width:80px">
<p:selectBooleanCheckbox value="#{returnBody.keyColumn}" id="key">
<p:ajax listener="#{createReturns.toggleCheckBox()}"
event="click" update="key">
<f:attribute name="element" value="#{returnBody.elementName}"></f:attribute>
</p:ajax>
</p:selectBooleanCheckbox>
</p:column>
</p:datatable>
actionlistener for command button to add empty rows in datatable
public void addReturnBodyToList() {
returnBody = new ReturnBody();
returnBodyList.add(returnBody);
}
ajax listener to uncheck other check boxes in bean
public void toggleCheckBox(ActionEvent actionEvent) {
String elementName = (String) actionEvent.getComponent()
.getAttributes().get("element");
for (ReturnBody body : returnBodyList) {
if (!body.getElementName().equals(elementName))
body.setKeyColumn(false);
System.out.println("Check ajax: " + body.toString());
}
}
You can achieve this in your toggleCheckBox() method.
boolean flag; //Global
String lastChecked=new String();//global
if(!flag){
setFlag(true);
lastChecked=elementName;
}
if(flag){
for (ReturnBody body : returnBodyList) {
if (body.getElementName().equals(lastChecked)){
body.setKeyColumn(false);
lastChecked=elementName;
}
}
}

submit button does not submit but only triggers InputText's onChange event

I am automatically selecting a value for radio button when the user types something in an input text using ajax.
The problem is: when the user types something in the input text and directly submits the form by clicking Get, the form does not submit but only the ajax is called because of the change event and the radio is updated.
A second click on the Get button, submits the form.
I also do not want to use keyup since it migth disturb the user while typing.
I use primefaces 5.1
here is my code:
<h:form id="myForm">
<p:selectOneRadio
value="#{myBean.include}" id="IncludeRadio">
<f:selectItem itemValue="Include" itemLabel="Include" />
<f:selectItem itemValue="Exclude" itemLabel="Exclude" />
<p:ajax process="#this" update="#form" />
</p:selectOneRadio>
<p:radioButton id="IncludeRadio0" for="IncludeRadio" itemIndex="0"/>
<p:radioButton id="IncludeRadio1" for="IncludeRadio" itemIndex="1"/>
<p:inputText
value="#{myBean.fieldValue}"
id="FieldValueInputText">
<p:ajax process="#this" update="#form" />
</p:inputText>
<p:commandButton id="GetButton"
action="#{myBean.execute}"
value="Get">
</p:commandButton>
</h:form>
and the bean:
#ManagedBean
#SessionScoped
public class MyBean {
public void setFieldValue(final String fieldValue) {
if (fieldValue != null && !fieldValue.trim().isEmpty()) {
if (!"Include".equals(getInclude())
&& !"Exclude".equals(getInclude())) {
setInclude("include");
}
} else {
setInclude("");
}
}
public void setInclude(String include) {
this.include = include;
}
public String getInclude() {
return this.include;
}
public void execute() {
// do something
}
}
submit button does not submit but only triggers InputText's onChange event
That happened because the blur event of the input field ajax-updates the submit button around the moment you click it. This way the JavaScript/Ajax logic associated with submit button is not guaranteed to work anymore, because the source element is removed from the DOM.
Make sure that you don't cover the submit button in the ajax update.
Instead of updating the entire form,
<p:ajax ... update="#form" />
update only the pieces which really need to be updated, which are only the inputs in your specific case:
<p:ajax ... update="IncludeRadio FieldValueInputText" />
Or if you'd rather like to not keep track of all those IDs when you have many inputs, grab PFS:
<p:ajax ... update="#(#myForm :input)" />

After closing p:dialog, event="dialogReturn" is not being called

I'm using PrimeFaces 5.2. Scenario:
Open a dialog to see the list
On dialog, show actions column at the end
Close the dialog
Redirect to selected action page in the column.
1, 2, 3 are working.
I have tried many things, but redirecting after closing it not working. dialogReturn method is not being called where I am calling the redirect code.
Here I am successfully loading a dialog in MyFile.xhtml.
<p:commandLink action="#{userDashboardBacking.showPriorityMyView()}"
class="myClass"
value="#{userDashboardBacking.priorityFilesLabel1} (#{userDashboardBacking.priorityFilesCount1})">
<p:ajax event="dialogReturn" update="#form" listener="#{userDashboardBacking.dialogReturn()}" />
</p:commandLink>
MyFileBacking.java
// this always get me to the required dialog/page
public void showPriorityMyView(){
Map<String, Object> options = new HashMap<String, Object>();
options.put("modal", true);
options.put("closable", true);
options.put("draggable", true);
options.put("resizable", true);
options.put("contentHeight", "500");
options.put("contentWidth", "1100");
RequestContext.getCurrentInstance().openDialog("priorityMyView", options, null);
}
// this method is never called.
public void dialogReturn(){
FacesContext facesContext = FacesContext.getCurrentInstance();
String outcome = "/myDetails.jsf?faces-redirect=true";
facesContext.getApplication().getNavigationHandler().handleNavigation(facesContext, null,outcome );
}
MyDetailDlg.xhtml
<p:column width="10">
<h:commandLink update="#form" action="#{myViewDlgBacking.selectedFileIdForDetails(row.fileId)}" title="View Details" immediate="true"
styleClass="ui-icon ui-icon-search" />
</p:column>
MyViewDlgBacking.java
// successfully closes the dialogue.
public void selectedFileIdForDetails(Long itemId){
RequestContext.getCurrentInstance().closeDialog(0);
}
Why is dialogReturn not being called and how can I redirect to another page after closing the dialog?
Change to java method without '()'
<p:ajax event="dialogReturn" update="#form" listener="#{userDashboardBacking.dialogReturn}" />
and add SelectEvent as input parameter to your method
public void dialogReturn(SelectEvent event){
Long selectedId = (Long) event.getObject();
}

Displaying Primefaces confirmDialog from Backing Bean

I have a Primefaces datatable and when the user clicks on a row, I display the data to edit in a form.
If the user changes the data in the form and clicks on any other row i.e if there is dirty data, I need to popup a confirmDialog to show if the user wants to save the data / discard it.
The confirmDialog does not display when I try to execute it from backing bean.
Any help is appreciated!
I have implemented it as follows:
.xhtml:
<p:dataTable id="tsTableId" value="#{transactionSetBean.studentList}" var="tsRow"
selectionMode="single" selection="#{transactionSetBean.selectedEditRec}" rowKey="#{tsRow.id}" scrollRows="10">
<p:ajax event="rowSelect" listener="#{transactionSetBean.onRowSelect}" update=":transactionSetsForm:tsEntryFrmId">
</p:ajax>
..
</p:dataTable>
ConfirmDialog:
<p:confirmDialog widgetVar="dataChangeDlg" message="Save changes Or Cancel">
<p:commandButton value="Save Changes" oncomplete="PF('dataChangeDlg').hide();"
update=":transactionSetsForm:messages :transactionSetsForm:tsEntryFrmId"
action="#{transactionSetBean.updateRecord}" />
<p:commandButton value="Cancel" onclick="PF('dataChangeDlg').hide();"
</p:confirmDialog>
Backing Bean:
public void onRowSelect(SelectEvent event)
{
String actionName = ON_ROW_SELECT;
try
{
Student selectedObj = (Student)event.getObject();
if (selectedObj != null)
{
selectedEditRec = selectedObj;
}
// if data is changed then show the dataChange dialog
if (isDataChanged())
{
setShowDataChangedDialog(true);
RequestContext context = RequestContext.getCurrentInstance();
// execute javascript and show dialog
context.execute("PF('dataChangeDlg').show();");
}
}
catch (Exception e)
{
handleException(e);
}
}
RequestContext.getCurrentInstance().execute("PF('dataChangeDlg').show();");
<p:ajax event="rowSelect" listener="#{transactionSetBean.onRowSelect}" update=":transactionSetsForm:tsEntryFrmId">
works for me.
There must be another error. maybe isDataChanged is false, wrong component ids in update or something.
With PrimeFaces >= 6.2
PrimeFaces.current().executeScript("PF('dataChangeDlg').show()");

Unable to disable <p:commandButton> via ajax

I want to disable the button in case there is no value in the input text something like this:
<p:autoComplete id="ac" value="#{bean.selectedNet}"
completeMethod="#{bean.complete}"
minQueryLength="0" size="3">
<p:ajax event="itemSelect" update="genButton" listener="#{bean.handleNetChange}"/>
<p:ajax process="#this" update="genButton" />
</p:autoComplete>
<p:selectManyCheckbox id="en" layout="pageDirection" value="#{bean.selectedEntity}">
<f:selectItems value="#{bean.entityList}"/>
<p:ajax update="genButton" listener="#{bean.handleNetChange}"/>
</p:selectManyCheckbox>
<p:commandButton id="genButton" value="Generate Files"
widgetVar="startButton1"
disabled="#{bean.disableButton}"
actionListener="#{bean.generate}"
onclick="PrimeFaces.monitorDownload(showStatus, hideStatus)"
ajax="false">
<p:fileDownload value="#{bean.streamedContent}"/>
</p:commandButton>
Methods:
public void handleNetChange() {
if (!StringUtils.isBlank(selectedNet) && !selectedEntity.isEmpty()) {
disableButton = false;
} else {
disableButton = true;
}
}
public List<String> complete(String query) {
List<String> results = new ArrayList<String>();
if (StringUtils.isBlank(query)) {
selectedNet = query;
disableButton = true;
} else {
....
}
return results;
}
While the itemSelect event is working perfectly the second one is not. I can see the call to the complete method in the bean but the button is not updated
Any advise?
Seems like you can't force update just with <p:ajax process="#this" update="genButton" />.
I would try to update the button directly from the bean.
Since you are using primefaces you can use RequestContext; try to add this line to your complete method :
RequestContext.getCurrentInstance().addPartialUpdateTarget("genButton");
If you don't use prependId="false" on your wrapping form, you might need to specify the full path to the button e.g.:
RequestContext.getCurrentInstance().addPartialUpdateTarget("fooForm:genButton");
If you want to use disabled, do not use rendered property on command button.
<p:commandButton id="buttonId"
actionListener="#{controller.function}"
value="#{controller.label}"
disabled="#{controller.disableButton}" rendered="#{controller.renderButton}" />
After removing rendered, button gets disabled without any issues.

Resources