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.
Related
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;
}
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.
I have JSF text box like this
<p:outputLabel value="#{msgs['label.responsible']}:" for="printingResponsibleEdit"
rendered="#{b2cOrderDetailBean.b2cActionOrderView.canChangePrintingInfo() and
b2cOrderDetailBean.b2cActionOrderView.showExecutionInfo}" />
<h:panelGroup id="printresponsible"
rendered="#{b2cOrderDetailBean.b2cActionOrderView.canChangePrintingInfo() and
b2cOrderDetailBean.b2cActionOrderView.showExecutionInfo}">
<p:inputText id="printingResponsibleEdit" value="#{b2cOrderDetailBean.b2cActionOrderView.printingResponsiblePersNr}" size="4"
valueChangeListener="#{b2cOrderDetailBean.changeListenerString}" required="true" immediate="true"
requiredMessage="#{msgs['msg.required']}" binding="#{printingResponsibleBinding}" maxlength="4">
<f:attribute name="historyTypeCode" value="PR" />
</p:inputText>
<h:outputText value=" " />
<p:commandButton value="#{msgs['button.ok']}" immediate="true" process="printingResponsibleEdit"
actionListener="#{b2cOrderDetailBean.requestPrintingResponsible}" escape="false"
update="printingResponsibleName printingResponsibleEditMsg">
<f:attribute name="printingResponsible" value="#{printingResponsibleBinding.localValue}" />
<f:param name="responsiblePersonName" value="#{b2cOrderDetailBean.b2cActionOrderView.printingResponsiblePersNr}"></f:param>
</p:commandButton>
<h:outputText id="printingResponsibleName" value=" #{b2cOrderDetailBean.b2cActionOrderView.printingResponsible}" />
</h:panelGroup>
<p:message id="printingResponsibleEditMsg" for="printingResponsibleEdit" />
And i have my managed beans method like this
public void requestPrintingResponsible(ActionEvent actionEvent) {
try {
b2cActionOrderView.setPrintingResponsible(null);
b2cActionOrderView.setPrintingResponsibleName(null);
b2cActionOrderView.setPrintingResponsiblePersNr(null);
String persNr = (String) actionEvent.getComponent().getAttributes().get("printingResponsible");
if (persNr != null) {
Account account = accountDelegate.findByPersNr(persNr, localeView.getLocale());
b2cActionOrderView.setPrintingResponsible(account.getAccountId());
b2cActionOrderView.setPrintingResponsibleName(account.getName());
b2cActionOrderView.setPrintingResponsiblePersNr(account.getPersNr());
validatedPrintingResponsible = account.getPersNr();
} else {
b2cActionOrderView.setPrintingResponsible(null);
}
} catch (NoDataFoundException e) {
LOG.warn("PersNr not found.", e);
b2cActionOrderView.setPrintingResponsible(null);
b2cActionOrderView.setPrintingResponsibleName(null);
b2cActionOrderView.setPrintingResponsiblePersNr(null);
MessageUtil.addFacesMessage("msg.notFound", colruyt.giftactionmgmt.util.Constants.MSG_PACKAGE, FacesMessage.SEVERITY_ERROR,
false, "form:tabView:printingResponsibleEdit", null);
}
}
My problem is when i enter a value that is there in the db and after that if i press ok button the corrensponding user name and user id is displayed but after that if i clear the value in the text box and if i press ok button must be filled error message is coming but the previous lable is not getting cleared.
ie(username,user id).
I have tried in many ways to achieve this can you guys help me
Your problem is clear immediate="true"
When you put immediate="true" on your commandButton you simply say to JSF please skip any validation on form (including printingResponsibleEdit) and process this action (requestPrintingResponsible)
So how can JSF validate printingResponsibleEdit and render an updated p:message(printingResponsibleEditMsg) if you have already skipped the validation phase , See More on JSF lifecycle
Put on your mind you have to render(update) every single component you want it to be updated after Ok button is pressed or simply you can make h:panelGroup container to your component and give it an ID and update it ex: <p:commandButton ... update='containerId'/>.
I am using JSF for my webapp (combined with EJB) and Bootsfaces as JavaScript addition to show modal windows. I am having a list of items that are being shown through a dataTable. And by clicking on a command button inside my list I am opening a modal window, asking the user "wether he is sure he wants to delete". That modal confirm dialog has YES and NO. I can execute the yes execute button inside the modal window. But I cant do #{controller.delete(item)} because the item is only server side available while building the list table. Somehow I have to send the actual selected item to the modal window to set it somehow in that controller call...???
Anyone got an idea?
<!-- looping the jsf list //-->
<h:dataTable value="#{controller.itemlist}" var="item"...
...
<!-- showing modal window //-->
<h:commandButton value="delete" action="" onClick="return false;" p:toggle-data.... />
</h:dataTable>
</h:form>
...
<!-- modal window in panel, with item not set //-->
...
<h:commandButton action="#{controller.delete(item)}" />
</h:form>
</b:panel>
...
You could use ajax to populate your modal's content :
$.ajax({
url : "yourPage.jsf",
type : "POST",
data : {
id: "your object's id"
},
dataType : "html"
}).done(function(html) {
$("#yourModal").html(html);
});
This ajax should be called with onclick event on your <h:commandButton>
And of course, you'd need to create a JSF view for your modal content. This view will contain your text and your two buttons "Yes" and "No". "No" should just dismiss your modal, while "Yes" should call your bean action : <h:commandButton action="#{controller.delete(item)}" />.
Don't forget to populate your controller item with the id parameter to bind data to your view.
EDIT :
I'll try to show you an example.
Main View (view.xhtml) :
<h:form>
<h:dataTable value="#{controller.itemlist}" var="item">
<h:column>
...
</h:column>
<h:column>
<h:commandButton value="delete" onclick="return populateModal(#{item.id}); " />
</h:column>
</h:dataTable>
</h:form>
Script to populate your modal (view.xhtml) :
<script type="text/javascript">
function populateModal(id) {
$.ajax({
url: "view2.jsf",
type: "POST",
data: { id: id },
dataType: "html"
}).done(function(html) {
$("#modal").html(html);
$("#modal").show();
});
return false;
}
</script>
Then you need a view for your modal's content (view2.xhtml) :
<h:form>
Delete #{testBean2.item.name} ?
<h:commandButton value="YES" action="#{testBean2.delete(testBean2.item)}" />
<h:commandButton value="NO" onclick="return closeModal();" />
</h:form>
And a controller for this view (testBean2.java) :
private Item item;
#PostConstruct
public void init() {
// GET id parameter from HTTPRequest
// Populate Local Item
}
public void delete(Item item) {
// Delete your item
}
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.