I have a problem with the function that disables the button. When I click button number one and it does not return the expected value - empty file, I want that button number two should be turned off.
However, it is not. The button number two is turns on and lets you download an empty file. What am I doing wrong?
file.xhtml
<p:commandButton value="Button1" update="#form" actionListener="#{test.generate}" ajax="true" />
<p:commandButton value="Button2" actionListener="#{test.download}" ajax="false" disabled="#{test.disableButton} />"
public boolean getDisableButton() {
return result == null ? true : false;
}
Related
I cannot comprehend JSF lifecycle for this particular case.
I'm trying to develop a simple modal CRUD with Primefaces 6.0, and I'm having problems with the beheaviour of the add/edit modal.
What I'm trying to accomplish is:
Add
Click add button
Add/Edit dialog opens
InputText "field1" is disabled=false
Edit
Click edit button
Add/Edit dialog opens
InputText "field1" is disabled=true
So for this I linked "field1" disabled property to editMode variable on my bean.
When I click Add Button, linked action initAddRubro gets fired and sets editMode = false (let's say that by default is true).
The thing is when I click on Add button without immediate=true, validations gets fired for the Add/Edit modal window (Field1 is required=true).
If I use immediate=true on my Add Button then disabled property does not get refreshed.
Faces Bean
#Component
#Scope("session")
public class RubrosFacesBean implements Serializable{
private boolean editMode = true;
public String initAddRubro(){
editMode = false;
return null;
}
}
Page
<p:commandButton value="Add" icon="ui-icon-plusthick"
oncomplete="PF('addPanelDialog').show();" style="float: right"
immediate="true" ajax="true" action="#{rubrosFacesBean.initAddRubro}"/>
<p:dialog header="Rubro" widgetVar="addPanelDialog" height="200" style="margin-left: auto;" modal="true" id="addPanelDialog" >
<p:messages autoUpdate="true" />
<p:panelGrid columns="2" id="addPanel">
<h:outputLabel for="field1" value="Field 1: " />
<p:inputText id="field1" value="#{rubrosFacesBean.field1}" label="Field1" required="true" disabled="#{rubrosFacesBean.editMode}"/>
</p:panelGrid>
</p:dialog>
Any help is appreciated.
Thanks in advance.
Juan.-
You can keep immediate="true" on your Add Button and just add following attribute to it
update="addPanel"
or
you can set immediate="false" and add following attributes
process="#this" update="addPanel"
Whatever option you choose, after you press Add button validation will be skipped, Ajax will be executed and finally p:panelGrid will be updated refreshing disable property of p:inputText.
Do not forget to do the same with your Edit button.
So I'm pretty new to jsf, I want a confirm dialog to be shown only if an attribute is set to true in my backing bean. I have something like this.
I have a data table which is multi selectable. When you select items in the table, an attribute get sets in the backing bean to hold those items.
Basically what the "showDeleteDialog()" method does, is check to see if any of those items in the list is selected, only then will it show the confirm dialog if the delete button is selected.
So what I want to happen is once a person has selected items from the data table, click the delete button. Have a confirm dialog come up and then delete the selected items. If the user has no items selected from the data table. I want the delete button to not show the confirm dialog.
<p:commandButton
styleClass="referralTaskDeleteBtn"
id="deleteButton"
value="#{loc['RegionAdmin.TaskType.DeleteButton']}"
icon="ui-icon-close"
update="deleteConfirmDialog,#this"
rendered="true"
action="#{referralTasksController.showDeleteDialog()}"
oncomplete="if (#{referralTasksController.displayDeleteDialog}) { PF('confirmDailogWidget').show(); }"
style="visibility: #{referralTasksController.toggleDeleteAndCompleteButtons()};"
disabled="#{not referralTasksController.enableEditButtons()}"
>
</p:commandButton>
and the backing bean method
public void showDeleteDialog(){
if (selectedReferralTasks.size()!=0)
this.displayDeleteDialog = true;
}
Anytime I click this, my dialog box only opens after the second click. Any ideas why? I'll include the dialog in case that is needed. Any help would be appreciate.
<p:outputPanel id="confirmationDailogOutputPanel">
<p:confirmDialog
id="deleteConfirmDialog"
header="Confirm Delete"
message="Are you sure you want to delete the selected Tasks"
showEffect="fade" hideEffect="fade"
widgetVar="confirmDailogWidget"
>
<p:commandButton value="#{loc['RegionAdmin.TaskType.DeleteButton']}" styleClass="confirmDialogDeleteButton" icon="ui-icon-check"
action="#{referralTasksController.deleteTasks()}"
oncomplete="PF('confirmDailogWidget').hide();"
update=":#{p:component('NoticePanel')},referralsTaskList,completeButton,deleteButton"
/>
<p:commandButton value="#{loc['RegionAdmin.TaskType.CancelButton']}"
styleClass="confirmDialogCancelButton"
icon="ui-icon-close"
oncomplete="PF('confirmDailogWidget').hide();"/>
</p:confirmDialog>
</p:outputPanel>
Problem explanation
In this oncomplete="if (#{referralTasksController.displayDeleteDialog}) { PF('confirmDailogWidget').show(); }" part of code you mixed ExpressionLanguage (#{referralTasksController.displayDeleteDialog}) and JavaScript code (everything else).
So when you load page Expression Language is evaluated (you can put a breakpoint to check this). At the first time when page is loaded of course evaluation return false. The code looks like this oncomplete="if (false) { PF('confirmDailogWidget').show(); }". It will never call show() method.
When page is reloaded (after button click) Expression Language is once again evaluated. Now code looks like this oncomplete="if (true) { PF('confirmDailogWidget').show(); }" (if you select data in datatable of course). This is a reason why dialog shows on second attempt.
Solutions
First: Runtime update
Remove oncomplete="if (#{referralTasksController.displayDeleteDialog}) { PF('confirmDailogWidget').show(); }"
Change bean method to
public void showDeleteDialog(){
if (selectedReferralTasks.size()!=0){
RequestContext.getCurrentInstance().execute("confirmDailogWidget.show()");
}
}
}
More about this solution you can found in PF documentation Misc > Request Context or in Open from bean by RequestContext#execute()
Second: Use p:confirmDialog rendered parameter
Remove oncomplete="if (#{referralTasksController.displayDeleteDialog}) { PF('confirmDailogWidget').show(); }"
Add rendered parameter to p:confirmDialog like this <p:confirmDialog rendered="#{referralTasksController.displayDeleteDialog}". Take a look at PF documentation and list of p:confirmDialog attributes
Change update parameter after button click to update confirmationDailogOutputPanel like this <p:commandButton update="confirmationDailogOutputPanel". Connected with Ajax update/render does not work on a component which has rendered attribute
I am using Eclipse Luna EE, Tomcat v7.0 and ICEFaces 3.2
I have a form for label printing that the user enters information such as item number, item name and label type. The user then submits the form. This sends the information to a label printer, in a ZPL string, which then prints out the correct label for the item. This all works no problem.
The form makes a check against the print quantity, in case of a high value (100+ in production). If the print quantity is over a certain value (> 2. purely for testing purposes) then the "testFlag" boolean is set to true, the modal box is displayed and an error flag is set so that the print command doesn't execute.
The modal box asks if the user entered the correct quantity, with Yes/No buttons available.
The printUI and the modal popup are inside the same <ice:form> element, with the popup box rendered and visible if the testFlag is set to true.
The Problem:
When I click the "Yes" button in the modal box, it doesn't carry out the action I have assigned to it (System.out.println("Yes Button!")). The modal box closes and nothing happens.
I can then resubmit the form and the modal box appears again, then I click "Yes" and nothing happens.
If I change the quantity to 2 and submit, then it executes the print command no problem.
I am guessing that it is a problem with the way the session is being handled.
Question:
How do I get the "Yes" button on the modal box to carry out the code I am wanting?
I've tried:
Using <ice:commandLink>, <h:button>, <h:commandButton>, <h:commandLink>
Having the modal popup and the form in separate <ice:form> tags (This refreshed the session and removed all entered data).
Using an actionListener
code containing the form:
<h:body>
<div id="surround">
<ice:form id="test" prependId="false">
<ui:include src="./printUI.xhtml" />
<ui:include src="./printQtyPopup.xhtml" />
</ice:form>
</div>
</h:body>
printQtyPopup.xhtml
<ui:composition>
<ice:panelPopup modal="true" visible="#{validateBean.testFlag}" rendered="#{validateBean.testFlag}">
<f:facet name="header">
<ice:outputText value="Print Quantity Check" />
</f:facet>
<f:facet name="body">
<ice:panelGrid>
<ice:outputText value="You selected a print quantity of: #{validateBean.printAmount}" />
<ice:outputText value="Is this correct?" />
<ice:panelGroup>
<ice:commandButton value="No" />
<ice:commandButton value="Yes" action="#{validateBean.checkQtyYes}" />
</ice:panelGroup>
</ice:panelGrid>
</f:facet>
</ice:panelPopup>
</ui:composition>
Relevant ValidateBean.java code
public void validate() { //validation checks are carried out when the user clicks "Print" on the printUI.
if (!errorFlag && checkQty && printQty > 2) {
testFlag = true;
errorFlag = true;
System.out.println("Qty Check Modal");
}
if (!errorFlag) {
if (printQty > 0) {
initialiseString();
initialisePrinter();
clear();
} else {
printQty = 0;
errorMessage = true;
quantityInvalid = true;
errorFlag = true;
}
}
}
public void checkQtyYes() {
System.out.println("Yes Button!");
}
I found an alternative.
I have removed the modal popup and any code linked with it.
I have added in a <ice:panelConfirmation> at the end of my form. This is only rendered if the print quantity is above whatever number I set.
I get the number by using a valueChangeListener="#{validateBean.printQtyChange}" on my Print Quantity <h:inputText> with onblur="submit()"
I tried the onchange="submit()" but ran into problems when submitting a string of print jobs. I would have to press "ENTER" to force the onchange attribute to activate, which I have been assured the users don't want.
The <ice:panelConfirmation> works by pausing the submit of the form and waits for a response before it either continues or stops the submit. Which accomplishes what I was trying to achieve with the modal popup.
Print Quantity Input Text:
<h:inputText id="printQty" value="#{validateBean.printAmount}" size="8" autocomplete="off"
maxlength="3" required="true" onblur="submit()"
valueChangeListener="#{validateBean.printQtyChange}" />
valueChangeListener:
public void printQtyChange(ValueChangeEvent e) {
printAmount = e.getNewValue().toString();
try {
ls.setPrintQty(Integer.parseInt(printAmount));
} catch (NumberFormatException eve) {
errorMessage = true;
quantityInvalid = true;
errorFlag = true;
}
printQty = ls.getPrintQty();
System.out.println("Qty : " +printQty);
if (printQty < 1) {
errorMessage = true;
quantityInvalid = true;
errorFlag = true;
}
}
Panel Confirmation: inside the <ice:form>. Just before the closing of the form
<ice:panelConfirmation id="confirmQty"
acceptLabel="Yes"
cancelLabel="No"
message="Your entered the quantity: #{validateBean.printQty}. Is this correct?"
title="Confirm Quantity"
draggable="false"
rendered="#{validateBean.printQty > 2}" />
Print Button: tied in with the <ice:panelConfirmation>
<ice:commandButton styleClass="button" id="printButton" value="Print"
actionListener="#{validateBean.validate}" panelConfirmation="confirmQty" />
If anyone does know of a way to invoke a managed bean from a conditional ICEfaces modal popup that would be great also.
UPDATE
I've since changed all my <h:inputText> to <ice:inputText> and added the partialsubmit="true" to my input field for the quantity. with adding this I have been able to remove the onblur="submit()"
NEW Print Quantity Input Text:
<ice:inputText id="printQty" value="#{validateBean.printAmount}" size="8" autocomplete="off"
maxlength="3" required="true" valueChangeListener="#{validateBean.printQtyChange}"
partialSubmit="true" />
This has removed the issue where sometimes it still had problems when submitting a string of jobs.
I haven't put partialsubmit="true" on the <ice:form> because I had to then declare every other input field as partialsubmit="false" to prevent unnecessary code being executed. It's tidier to only have it on the input field I want to check.
JSF 2.0, Mojarra 2.0.1, PrimeFaces 3.4.1
Here is a p:inputText component which is expected to call a backing bean method when the enter key is pressed.
<p:inputText id="commentInput" rendered="#{status.haveComment}"
value="#{statusBean.newComment}"
onkeypress="if (event.keyCode == 13) { onchange(); return false; }">
<f:ajax event="change" listener="#{statusBean.test}" />
</p:inputText>
While backing bean has the method of:
public void test(AjaxBehaviorEvent event) {
System.out.println("Pressed enter!");
}
It's calling method when enter key is pressed but it has more than this; unexpected behaviour case:
--Click input text
----Type some letters
------Click somewhere else in the page
--------CONSOLE: Pressed enter!
I think ajax event=change detects a change somehow and calls the method. How to convert this p:inputText component into a proper comment taker component like Facebook or others has?
This is the way how onchange event works in HTML. It is happening when text in input element is changed, but is fired when component loses focus (in your case that is the moment when you click somewhere else in the page).
You can define p:remoteCommand for test method and just write:
<p:remoteCommand name="test" actionListener="#{statusBean.test}"/>
<p:inputText id="commentInput" rendered="#{status.haveComment}"
value="#{statusBean.newComment}"
onkeypress="if (event.keyCode == 13) { test(); return false; }"/>
and in backing bean:
public void test() {
System.out.println("Pressed enter!");
}
With newer PrimeFaces versions (5+ at least) you can use p:defaultCommand instead of scripting. Though you can't use p:remoteCommand then, because p:defaultCommand needs something clickable.
<p:inputText id="input" />
<p:defaultCommand target="submit" />
<!--you can show the button to allow the user to click too, or hide it with display: none-->
<p:commandButton id="submit" style="display: none;" process="input" />
By default p:defaultCommand applies to the whole form. You could limit it with the scope attribute.
I have a form in JSF2 with 2 checkboxes (<h:selectBooleanCheckbox>). At least one of them should be checked. Both checked are also ok, but when none is checked, there should be error.
This validation should work also on ajax, i.e. when user checks/unchecks, error message should disappear/appear.
So I binded both checkboxes to UISelectBoolean elements and added validator to each. In validator I check value of the second checkbox, if it is false, and current checkbox is also set to false, errormessage is produced. Smth like:
if (newValue == false && secondCheckbox.getValue() == false) {
throw new ValidationException();
}
Problem is when user unchecks checkbox on the page, while the other is also unchecked, this false value doesn't go to the model, nor event to UISelectBoolean.
Scenario:
Initially both are unchecked
User checks checkbox1.
newValue is true, so this is valid, goes to UISelectBoolean and model.
User unchecks checkbox1. Checkbox2 is false, newValue is false, so exception is thrown.
Because of failed validation, this false value doesn't go to the model, nor even to UISelectBoolean element.
User checks checkbox2. True value goes to the model and UISelectBoolean.
User unchecks checkbox2. Checkbox1 is still unchecked on the page, but in the model and UISelectBoolean there is still true. So validation passes and there is no error message. On the page both checkboxes are unchecked, but in model checkbox1 is still true.
How to solve such a problem?
Consider <h:selectManyCheckbox required="true">. Here's a kickoff example:
<h:form>
<h:selectManyCheckbox id="options" value="#{bean.checked}" required="true">
<f:selectItems value="#{bean.options}" />
<f:ajax render="optionsMessage" />
</h:selectManyCheckbox>
<h:message id="optionsMessage" for="options" />
<h:commandButton value="Submit" action="#{bean.submit}">
<f:ajax execute="#form" render="#form" />
</h:commandButton>
<h:messages globalOnly="true" />
</h:form>
With
#ManagedBean
#RequestScoped
public class Bean {
private List<String> checked;
private List<String> options = Arrays.asList("first", "second");
public void submit() {
System.out.println("Checked: " + checked);
}
// ...
}
The f:ajax works fine here. Probably you've used event="click" instead of (the default) event="valueChange" which will cause that the checkmark won't be retained after render. The click is namely called right before the checkmark get visually set. The render would block the checkmark being visually set.