Variable name in EL Expression 2.2 - jsf

I feel a little dumb: I am using Primefaces on Tomcat 7 and would like to use those fancy new EL expressions to reduce some code clutter. I figured out how to do this in datatables but I can't get it to work otuside recurring structures which have those handy var attributes. How would I declare the EL parameter for grantRole(String) to be the value of the inputText?
<h:panelGrid columns="3">
<h:outputText value="Name" />
<p:inputText/>
<p:commandButton value="Add" update="associatedPlayers"
action="#{permissionRoleDetailBean.grantRole(associatePlayerName)}" />
</h:panelGrid>

You could do so:
<h:panelGrid columns="3">
<h:outputText value="Name" />
<p:inputText binding="#{playerName}" />
<p:commandButton value="Add" update="associatedPlayers"
action="#{permissionRoleDetailBean.grantRole(playerName.value)}" />
</h:panelGrid>
However, this makes no sense. The normal approach is the following:
<h:panelGrid columns="3">
<h:outputText value="Name" />
<p:inputText value="#{permissionRoleDetailBean.playerName}" />
<p:commandButton value="Add" update="associatedPlayers"
action="#{permissionRoleDetailBean.grantRole}" />
</h:panelGrid>
with
private String playerName; // +getter+setter
public void grantRole() {
System.out.println(playerName); // Look, it's already set by JSF.
}

Related

Primefaces Mobile commandButton not working with ActionListener

I presented the following problem.
when done click the button located in the dialog (pop -up ), the actionListener attribute does not work , ie not call the Backingbean.
The strange thing is that in the version PrimeFaces showcase this code works perfectly , only mobile fails.
Another curiosity is that the javascript function button is successful, what makes me think it's a problem of ajax for mobile version
Here the code
<pm:content>
<h:form id="productForm">
<p:dataList value="#{productoMB.productList}" var="pro"
paginator="true" id="productDL">
<f:facet name="header">Menu de comidas</f:facet>
<p:panel header="#{pro.name}" style="text-align:center">
<h:panelGrid columns="1" style="width:100%">
<p:commandLink update=":homeFirst:productForm:productDetail"
oncomplete="PF('productDialog').show()" title="Ver Detalles">
<h:graphicImage library="images" name="#{pro.path}" width="320px"
height="120px" />
<f:setPropertyActionListener value="#{pro}"
target="#{productoMB.productSelect}" />
</p:commandLink>
</h:panelGrid>
</p:panel>
</p:dataList>
<p:dialog header="Detalle Plato" widgetVar="productDialog"
modal="true" showEffect="fade" hideEffect="fade" resizable="false">
<p:outputPanel style="text-align:center;">
<p:panelGrid id="productDetail" columns="2"
rendered="#{not empty productoMB.productSelect}"
columnClasses="label,value">
<f:facet name="header">
<p:graphicImage library="images"
name="#{productoMB.productSelect.path}.jpg" width="100px"
height="100px" />
</f:facet>
<h:outputText value="Nombre:" />
<h:outputText value="#{productMB.productSelect.name}" />
<h:outputText value="Precio" />
<h:outputText value="#{productoMB.productSelect.price}" />
<h:outputText value="Detalles:" />
<h:outputText value="#{productoMB.productSelect.description}" />
<h:outputText value="Cantidad:" />
<h:inputText value="#{productoMB.quantity}" required="true">
<!-- <p:ajax update="costo" listener="#{empMB.calcularPrecioTotal}" /> -->
<!-- <f:validateDoubleRange minimum="0" maximum="200" /> -->
</h:inputText>
<h:outputText value="Total a Pagar:" />
<!-- <h:outputText id="costo" value="#{empMB.precioTotal}" /> -->
<p:commandButton value="Volver"
onclick="PF('productDialog').hide()"></p:commandButton>
<h:form>
<p:commandButton value="Agregar al carrito"
onclick="PF('carDialog').hide()" icon="ui-icon-cart" actionListener="#{productoMB.addCart}">
</p:commandButton>
</h:form>
</p:panelGrid>
</p:outputPanel>
</p:dialog>
</h:form>
</pm:content>
This is a backingbean
package ar.com.as.presentation.mb;
import java.util.ArrayList;
import java.util.List;
import ar.com.as.business.bo.interfaces.GenericBO;
import ar.com.as.business.bo.patterns.FactoryFacade;
import ar.com.as.model.Cart;
import ar.com.as.model.Product;
public class ProductMB {
private List<Product> productList;
private Product productSelect;
private int quantity;
private List<Cart> cartList;
public ProductMB() {
productList = new ArrayList<Product>();
cartList = new ArrayList<Cart>();
findAllProduct();
}
public void findAllProduct() {
GenericBO<Product> productBO = FactoryFacade.createFacade("facade")
.getInstance().create("product");
productList = productBO.findAll();
}
public void addCart() {
System.out.println("se agrego al carrito");
}
// Getters+setters.
}
Any idea Como esta Problem solved .Or How to run the method addcart without ajax .
From already thank you very much .
Regards, Santiago
You have a nested h:form. Correct that, since it will very often (~always) lead to unexpected behaviour. Working in one environment and not in another is one of them.
Related Stackoverflow posts
I share the solution I found to my particular problem is:
<p:commandButton value="add" onclick="addC()"
icon="ui-icon-plus"
style="margin-left:20%; margin- rigth:15%" >
</p:commandButton >
In the onclick call javascript function addC:
<p:remoteCommand name="addC"
actionListener="#{productoMB.addCart}"
update="#widgetVar(cart)" />
RemoteCommand provides a simple way to execute backing bean methods with javascript.
Apparently mobile PrimeFaces has some bugs and does not work correctly with ajax.
Regards, Santiago

Convert Java EE 7 EL Map to a dynamic value from a forEach loop

I currently have a task to dynamically generate content that is now static. The problem is that the sessionScope variable from EL is used to toggle the rendering of content. Since sessionScope is a Map, I don't really know how to convert it to be used in a forEach loop.
Current layout:
<p:outputPanel layout="block">
<p:commandLink id="testId">
<p:graphicImage value="#{request.contextPath}/images/test.jpg" />
<f:setPropertyActionListener value="#{!sessionScope.renderContentA}" target="#{sessionScope.renderContentA}" />
</p:commandLink>
<pe:tooltip for="testId" value="TestTooltip" />
</p:outputPanel>
<p:outputPanel layout="block">
<p:commandLink id="testId2">
<p:graphicImage value="#{request.contextPath}/images/test2.jpg" />
<f:setPropertyActionListener value="#{!sessionScope.renderContentB}" target="#{sessionScope.renderContentB}" />
</p:commandLink>
<pe:tooltip for="testId2" value="TestTooltip" />
</p:outputPanel>
Which I need to convert to:
<c:forEach items="#{bean.items}" var="item">
<p:outputPanel layout="block">
<p:commandLink id="#{item.id}">
<p:graphicImage value="#{request.contextPath.concat(item.imageUrl)}" />
<f:setPropertyActionListener value="#{!SOMETHING-HERE}" target="#{SOMETHING-HERE}" />
</p:commandLink>
<pe:tooltip for="#{item.id}" value="TestTooltip" />
</p:outputPanel>
</c:forEach>
An example where it's used (which I need to adjust aswell):
<p:outputPanel autoUpdate="true" style="float: right;">
<p:commandLink rendered="#{!sessionScope.renderContentA}">
<h:outputText styleClass="ui-icon ui-icon-plus" />
<f:setPropertyActionListener value="#{!sessionScope.renderContentA}" target="#{sessionScope.renderContentA}" />
</p:commandLink>
<p:commandLink rendered="#{sessionScope.renderContentA}">
<h:outputText styleClass="ui-icon ui-icon-minus" />
<f:setPropertyActionListener value="#{!sessionScope.renderContentA}" target="#{sessionScope.renderContentA}" />
</p:commandLink>
</p:outputPanel>
I've been Googling for a while now, but can't find a good answer. I'm using Glassfish 4, Java EE 7, EL 3 and JSF 2.1.1-b04. If I need to provide something else, please let me know.
I found the sollution after some trial and error with a collegue. You can access sessionScope with a plain array-like approach.
<f:setPropertyActionListener value="#{!sessionScope[item.uniqueName]}" target="#{sessionScope[item.uniqueName]}" />

primefaces datatable not working properly

Following XHTML code for primefaces datatable.
<h:panelGroup id="mode">
<p:panelGrid columns="2">
<p:panelGrid columns="2">
<p:outputLabel style="font-weight: bold;"
value="Mode Of Payments" />
<p:selectOneRadio value="#{invoiceBean.modeOfPayment}"
layout="pageDirection">
<f:ajax render="mode" />
<f:selectItem itemLabel="Cash" itemValue="Cash" />
<f:selectItem itemLabel="Cheque" itemValue="Cheque" />
</p:selectOneRadio>
<p:outputLabel value="Enter Bank Name :" />
<p:inputText value="#{invoiceBean.bankName}"
disabled="#{invoiceBean.modeOfPayment == 'Cash'}" />
<p:outputLabel value="Enter Cheque Number :" />
<p:inputText value="#{invoiceBean.chequeNumber}"
disabled="#{invoiceBean.modeOfPayment == 'Cash'}" />
<p:outputLabel value="Enter Amount :" />
<p:inputText value="#{invoiceBean.chequeAmount}" />
</p:panelGrid>
<p:panelGrid columns="1">
<p:dataTable id="transactionTable"
value="#{invoiceBean.transactions}" var="transaction">
<p:column headerText="Mode Of Payment">
<p:outputLabel value="#{transaction.modeOfPayment}" />
</p:column>
<p:column headerText="Bank Name">
<p:outputLabel value="#{transaction.bankName}" />
</p:column>
<p:column headerText="Amount">
<p:outputLabel value="#{transaction.chequeAmount}" />
</p:column>
<p:column headerText="Balance">
<p:outputLabel value="#{transaction.balance}" />
</p:column>
<p:summaryRow>
<p:column colspan="3">
<p:outputLabel value="Remaining Balance" />
</p:column>
<p:column>
<p:outputLabel value="#{transaction.balance}" />
</p:column>
</p:summaryRow>
</p:dataTable>
</p:panelGrid>
</p:panelGrid>
</h:panelGroup>
<p:commandButton value="Save New Invoice"
action="#{invoiceBean.addRow}"
update=":form:invoiceTable :form:transactionTable growl"
process="#form invoiceTable" onclick="PF('addInvoice').hide();">
<f:ajax render=":form:transactionTable" />
<f:ajax render=":form:invoiceTable" />
</p:commandButton>
Following managed beans code for transactionTable :
#PostConstruct
public void init() {
session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
transactionDao = new TransactionDao();
invoiceDao = new InvoiceDao();
invoices = invoiceDao.getInvoiceData(invoiceNumber);
transactions = transactionDao.getTransactions(invoices.get(0).getId());
invoiceProductsServicesDetails = invoiceDao
.getInvoiceProductsServicesDetailDatas();
}
When I add new record in HTML table it will display in transactionTable when click on "Save New Invoice".
Its work first time properly but when I click on radio button and select "Cheque" option new data not display and its replace old data.
You're not supposed to perform business logic in getters/setters.
A normal getter/setter pair looks like this (exactly like as the average IDE would autogenerate for you):
public List<Transaction> getTransactions() {
return transactions;
}
public void setTransactions(List<Transaction> transactions) {
this.transactions = transactions;
}
You should never change them unless you really know what you're doing. In your particular case, the <p:dataTable> calls the getter on every iteration round. You're basically calling the DAO for every single row. This doesn't make sense. This has a huge performance impact if there are lots of records.
In order to preload the data for view, one of the ways is a #PostConstruct method (the bean should preferably be #ViewScoped for this kind of view):
#PostConstruct
public void init() {
transactions = transactionDao.getTransactions(invoices.get(0).getId());
}
In order to save/update the data after edit, just use the action(listener) method.
See also:
Why JSF calls getters multiple times

how to update h:panelGroup using f:ajax

How to update h:panelGroup using f:ajax.When, i select h:selectBooleanCheckbox getting value from officeAdd1 and set this value into headOfficeAdd1.Am getting officeAdd1 value in bean but i want to update value into headOfficeAdd1.
Thanks...
<h:form id="form">
<p:panel id="display">
<p:spacer width="20" />
<h:panelGrid columns="6">
<h:outputLabel value="Address:"
style="text-align: left;display: block;width:130px;" />
<p:inputTextarea
value="#{companyInformationBean.current.officeAdd1}"
autoResize="true" style="width:170px;" maxlength="150" />
</h:panelGrid>
<h:panelGrid columns="6">
<h:selectBooleanCheckbox id="remember"
value="#{companyInformationBean.current.checkBox}">
<f:ajax event="click" execute="#form"
listener="#{companyInformationBean.checkBoxValue}" />
</h:selectBooleanCheckbox>
<h:outputLabel value="Same as Registered Office Address"
style="text-align: left;display: block;" />
<p:spacer width="20" />
</h:panelGrid>
<p:spacer width="20" />
<h:panelGroup id="hidepanelgroup">
<h:panelGrid id="getaddress" columns="6">
<h:outputLabel value="Head Office Address:"
style="text-align: left;display: block;width:130px;" />
<p:inputTextarea id="headadd"
value="#{companyInformationBean.current.headOfficeAdd1}"
autoResize="true" style="width:170px;" maxlength="150" />
</h:panelGrid>
</h:panelGroup>
</p:panel>
</h:form>
Bean:
public void checkBoxValue()
{
if(current.getCheckBox()==true)
{
logger.info("getofadd"+current.getOfficeAdd1());
current.setHeadOfficeAdd1(current.getOfficeAdd1());
}
else
{
logger.info("checkbox value false");
}
}
You need to specify client IDs-to-render in the <f:ajax render> attribute.
Thus, given that the second textarea has an ID of headadd, this should do:
<f:ajax ... render="headadd" />
Unrelated to the concrete problem, comparing booleans against booleans in a boolean expression really doesn't make any sense. Just check the boolean itself directly.
if (current.getCheckBox())
By the way, try to use self-documenting property and method names. A property name of remember would be more suitable.

How to stay in the dialog if OK button `action` reports error? [duplicate]

I have a CRUD page which shows data from a query (a List of domain objects) in a Primefaces datatable.
<p:dataTable
id="negozi"
var="n"
value="#{nController.theListFromQuery}"
rowKey="#{n.id}"
selection="#{nController.selected}"
selectionMode="single">
<p:column headerText="Field1">
<h:outputText value="#{n.f1}" />
</p:column>
<p:column headerText="Field2">
<h:outputText value="#{n.f2}" />
</p:column>
<p:column style="width:4%">
<p:commandButton
actionListener="#{nController.prepareEdit(n)}"
update=":editDialogId"
oncomplete="editDialog.show()"
value="Edit" />
</p:column>
...
By clicking on the edit button a dialog will be shown:
<p:dialog
header="Edit N"
widgetVar="editDialog"
id="editDialogId">
<h:form id="formDialog">
<h:panelGrid id="editDialogTable" columns="2" cellpadding="10" style="margin:0 auto;">
<p:outputLabel for="field1" value="F1:" />
<p:inputText id="field1" value="#{nController.selected.f1}" />
<p:outputLabel for="field2" value="F2:" />
<p:inputText id="field2" value="#{nController.selected.f2}" />
<p:commandButton
value="Confirm"
actionListener="#{nController.doEdit}"
update=":form"
oncomplete="editDialog.hide()"
rendered="#{nController.selected.id!=null}" />
...
It works. Now I want to make F1 a required field.
I add the "required" attribute to the inputText field and what happens?
When I try to confirm the form without the required field, the entity is not edited (that's right) but the dialog is closed (that's NOT right!)
When I reopen the dialog I can see the red highlight on the required (and invalid) field.
What I want is to prevent the dialog closing if the form is invalid.
Do I have to write some JS or will JSF help me?
The PrimeFaces ajax response puts an args object in the scope which has a validationFailed property. You could just make use of it.
oncomplete="if (args && !args.validationFailed) PF('editDialog').hide()"
(the args precheck is necessary to not cause a JS error when an exception is thrown during request)
You could refactor it to a reusable JS function as follows.
oncomplete="hideDialogOnSuccess(args, 'editDialog')"
function hideDialogOnSuccess(args, dialogWidgetVar) {
if (args && !args.validationFailed) {
PF(dialogWidgetVar).hide();
}
}
this post is now three years old, but I have found helpful, so my findings may help others.
In PF 5.x at least, it seems that the solution provided by BalusC has to be modified in two ways. (1) add the "args" argument to the call in oncomplete event hander, and (2) use the PF primefaces primitive to identify the widget in PF tables. Here is the code I am using:
oncomplete="hideDialogOnSuccess(args, PF('editDialog'))"
function hideDialogOnSuccess(args, dialogWidgetVar) {
if (args && !args.validationFailed) {
dialogWidgetVar.hide();
}
}
I believe this is the cleanest solution.
Doing this you don't need to change your buttons code.
This solution overrides the hide function prototype.
$(document).ready(function() {
PrimeFaces.widget.Dialog.prototype.originalHide = PrimeFaces.widget.Dialog.prototype.hide; // keep a reference to the original hide()
PrimeFaces.widget.Dialog.prototype.hide = function() {
var ajaxResponseArgs = arguments.callee.caller.arguments[2]; // accesses oncomplete arguments
if (ajaxResponseArgs && ajaxResponseArgs.validationFailed) {
return; // on validation error, prevent closing
}
this.originalHide();
};
});
This way, you can keep your code like:
<p:commandButton value="Save" oncomplete="videoDetalheDialogJS.hide();"
actionListener="#{videoBean.saveVideo(video)}" />
to keep the dialog Open on validation Failed, you just need set the commandButton as follows:
<p:commandButton value="save"
action="#{YourBean.yourActionMethod}"
oncomplete="if (!args.validationFailed) PF('yourDialogWidgetVar').hide()"/>
I gonna leave here a complete example:
<h:form id="ad-form">
<p:dialog id="ad-dialog" widgetVar="adDialog" modal="true" width="400"
closeOnEscape="true" resizable="false" header="Addreass">
<p:messages id="a-msgs" closable="true" />
<h:panelGrid columns="2" id="ad-painel-dialog" width="100%">
<p:outputLabel value="Country" for="country" />
<p:inputText id="country" style="width:100%"
value="#{clientSaverBean.editableAddress.country}" />
<p:outputLabel value="City" for="city" />
<p:inputText id="city"
value="#{clientSaverBean.editableAddress.city}" />
<p:outputLabel value="Zip-Code" for="zipcode" />
<p:inputText id="zipcode"
value="#{clientSaverBean.editableAddress.zipCode}" />
<p:outputLabel value="Street" for="street" />
<p:inputTextarea id="street"
value="#{clientSaverBean.editableAddress.street}" />
<p:outputLabel value="Number" for="number" />
<p:inputText id="number"
value="#{clientSaverBean.editableAddress.number}" />
<h:panelGroup />
<f:facet name="footer">
<p:commandButton value="save"
action="#{clientSaverBean.saveAddress}"
process=":ad-form:ad-dialog"
update=":ad-form:a-msgs :ad-form:ad-painel-dialog :client-form:ad-table"
oncomplete="if (!args.validationFailed) PF('adDialog').hide()"/>
</f:facet>
</h:panelGrid>
</p:dialog>
</h:form>

Resources