Conditionally rendering a primefaces commandlink - jsf

I'm trying to conditionally render a commandlink. However I discovered when debugging the bean function stocksView.hasPortfolios is never called. Is this the correct way to user render or should I be doing this in another way?
<h:form id="form">
<p:dataGrid id="prices" var="orderBooks" value="#{stocksView.latestPricesResults}" columns="3" rows="12">
<f:facet name="header">
WST 100
</f:facet>
<p:column>
<p:panel header="#{orderBooks.bidOrderId.member.memberId}">
<h:panelGrid columns="1">
<h:outputText value="#{orderBooks.price}" />
<h:outputText value="#{orderBooks.bidOrderId.member.party}" />
<h:outputText value="#{orderBooks.lastUpdate}" />
<p:commandLink update=":form:buyDetail" oncomplete="PF('buyDialog').show()" title="View Detail">
<h:outputText value="Buy"/>
<f:setPropertyActionListener value="#{orderBooks}" target="#{stocksView.selectedStock}" />
</p:commandLink>
<p:commandLink update=":form:sellDetail" oncomplete="PF('sellDialog').show()" title="View Detail" rendered="#{stocksView.hasPortfolios[orderBooks.bidOrderId.member.memberId]}">
<h:outputText value="Sell"/>
<f:setPropertyActionListener value="#{orderBooks}" target="#{stocksView.selectedStock}" />
</p:commandLink>
</h:panelGrid>
</p:panel>
</p:column>
</p:dataGrid>
</h:form>
This is the hasPortfolios method in StocksView (which is a ViewScoped Bean). The hasPortfolios variable is private Map hasPortfolios;
public void hasPortfolios(){
hasPortfolios = new HashMap<Boolean,String>();
Collection<Portfolio> portfolios = user.getTrader().getPortfolios();
Iterator<Portfolio> iter = portfolios.iterator();
while(iter.hasNext()){
Portfolio p = iter.next();
if(p.getBalance() == 0){
hasPortfolios.put(false, p.getMember().toString());
logger.log(Level.INFO, "hasPortfolios false");
}
else
{
hasPortfolios.put(true,p.getMember().toString());
logger.log(Level.INFO, "hasPortfolios true");
}
}
}

To my eyes you should call the function like this instead of using square brackets:
rendered="#{stocksView.hasPortfolios(orderBooks.bidOrderId.member.memberId)}
Also make sure its public and there is not overloaded version of it.

As usual I was doing a few things wrong. Firstly my map returns a Boolean object in the rendered attribute, and this has to be a boolean primitive. So to get around that I call booleanValue()
rendered="#{stocksView.hasPortfolios[orderBooks.bidOrderId.member.memberId].booleanValue()}"
Also I had my map key/value in the wrong order so the Boolean was actually the key instead of the Member ID.
And finally, I was calling getMember().toString() which returns the Member object as a String, rather than the actual Member ID string which is returned by calling getMember().getMemberId(). So hasPortfolios should actually look like this:
public void hasPortfolios(){
logger.log(Level.INFO, "hasPortfolios start");
hasPortfolios = new HashMap<String,Boolean>();
Collection<Portfolio> portfolios = user.getTrader().getPortfolios();
Iterator<Portfolio> iter = portfolios.iterator();
while(iter.hasNext()){
Portfolio p = iter.next();
if(p.getBalance() == 0){
hasPortfolios.put(p.getMember().getMemberId(),new Boolean(false));
logger.log(Level.INFO, "hasPortfolios false");
}
else
{
hasPortfolios.put(p.getMember().getMemberId(),new Boolean(true));
logger.log(Level.INFO, "hasPortfolios true");
}
}
}
The Sell commandlink is now rendered when there is a portfolio for the user.
Thanks for your help everyone, it pointed me in the right direction.

Related

Data Table Primefaces

I'm working with JSF Primefaces and I want to make a search and show results in but results won't show, I'm doing this with Result type and had implemented like this in JSF 2.1 whith MyFaces tomahawk, but now with primefaces this doesn't work, here is my code
<h:form id="buscar_sucursal">
<p:panel style="width: 800px">
<h:panelGrid columns="5">
<h:outputText value="Criterio: " />
<p:selectOneMenu id="citerio" value="#{SucursalesBean.criterio}">
<f:selectItem itemValue="1" itemLabel="CVE SUCURSAL"></f:selectItem>
<f:selectItem itemValue="2" itemLabel="NOMBRE"></f:selectItem>
</p:selectOneMenu>
<h:outputText value="Valor: " />
<p:inputText id="valor" value="#{SucursalesBean.valor}"></p:inputText>
<p:commandButton action="#{SucursalesBean.buscar}" value="Buscar"></p:commandButton>
</h:panelGrid>
</p:panel>
<p:dataTable id="sucursalesTable" var="suc" value="#{SucursalesBean.sucursalesTable}">
<p:column headerText="Id">
<h:outputText value=""></h:outputText>
</p:column>
<p:column headerText="Cve">
<h:outputText value="#{suc.cve_sucursal}"></h:outputText>
</p:column>
<p:column headerText="Sucursal">
<h:outputText value="#{suc.sucursal}"></h:outputText>
</p:column>
<p:column headerText="Domicilio">
</p:column>
<p:column headerText="Contraseña">
</p:column>
<p:column headerText="Accion">
<h:commandLink value="Editar"></h:commandLink> /
<h:commandLink value="Eliminar"></h:commandLink>
</p:column>
</p:dataTable>
</h:form>
And the code of my ManagedBean
public Result getSucursalesTable()
{
return this.sucursalesTable;
}
public void setSucursalesTable(Result sucursalesTable)
{
this.sucursalesTable = sucursalesTable;
}
public void buscar() throws ClassNotFoundException
{
HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
this.valor = request.getParameter("buscar_sucursal:valor");
try
{
LoginBean loginBean = (LoginBean) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("LoginBean");
Connection conn = loginBean.getConectar_db();
//int id_empresa = loginBean.getId_empresa();
ArrayList<SucursalesBean> al = new ArrayList<SucursalesBean>();
st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = null;
//ResultSet rs = st.executeQuery("SELECT *FROM clientes WHERE id_cliente='"+request.getParameter("id_cliente")+"';"); // AND id_contribuyente='' AND id_empresa=''
//if(request.getParameter("sucursales:id_sucursal") != null)
//rs = st.executeQuery("SELECT *FROM sucursales WHERE id_sucursal='"+request.getParameter("sucursales:id_sucursal")+"' AND id_empresa='"+loginBean.getId_empresa()+"' AND id_contribuyente='"+loginBean.getId_contribuyente()+"';"); // AND id_contribuyente='' AND id_empresa=''
if(getCriterio().toString() != null)
{
if(getCriterio().toString().equals("1"))
rs = st.executeQuery("SELECT cve_sucursal,sucursal FROM sucursales WHERE cve_sucursal='"+this.valor+"' AND id_empresa='"+loginBean.getId_empresa()+"' AND id_contribuyente='"+loginBean.getId_contribuyente()+"';");
if(getCriterio().toString().equals("2"))
rs = st.executeQuery("SELECT *FROM sucursales WHERE sucursal LIKE '%"+this.valor+"%' AND id_empresa='"+loginBean.getId_empresa()+"' AND id_contribuyente='"+loginBean.getId_contribuyente()+"';");
}
this.sucursalesTable = ResultSupport.toResult(rs);
//this.sucursalesTable = rs;
//setSucursalesTable(ResultSupport.toResult(rs));
/*while(rs.next())
{
//out.println("<tr><td>"+rs.getString("sucursal")+"</td><td>"+rs.getString("cve_sucursal")+"</td><td>"+rs.getString("telefono")+"</td><td>"+rs.getString("e_mail")+"</td><td>"+rs.getString("calle")+"</td><td><a href='sucursales.jsp?accion=editar&id_sucursal="+rs.getString("id_sucursal")+"'>Editar</a></td><td></td></tr>");
//setId_sucursal(String.valueOf(rs.getInt("id_sucursal")));
setCve_sucursal(rs.getString("cve_sucursal"));
setSucursal(rs.getString("sucursal"));
al.add(this);
}
this.sucursalesTable = al;*/
}
catch(SQLException ex)
{
}
}
I don't want to use serialized objects in order to use List type because I think it's to much code for doing something that supposed to be simple, even if this it's not the best aproach.
My doubt it's if Primefaces has support for Result type or am I lost with this and maybe that's why this aproach isn't working.
Any help I really appreciate thank in advance
It looks to me as you've converted a h:commandButton to p:commandButton. The first by default uses non-ajax request, but the latter uses an ajax request. If correct, you just need to tell the button which components to process during and update after the request:
<p:commandButton action="#{SucursalesBean.buscar}"
value="Buscar"
process="criterio valor"
update="sucursalesTable" />
Or use a non-ajax request:
<p:commandButton action="#{SucursalesBean.buscar}"
value="Buscar"
ajax="false" />

javax.faces.view.facelets.TagAttributeException

I'm creating a small application using JSF,facing the exception, below is the code for the form.
<h:form>
<h:selectManyCheckbox value="#{transferMB.selectedItems}">
<f:selectItem itemValue="1" itemLabel="Transfer Status" />
<p:ajax update=":transForm" />
</h:selectManyCheckbox>
</h:form>
exception " javax.faces.view.facelets.TagAttributeException:"
This is a follow-up for issue while loading data
As mentioned there, you need to use EL 2.2 for passing parameter inside EL-Expressions. Seems you don't use that.
So we need another way to get this solved:
<h:form id="transForm">
<p:panelGrid columns="1" rendered="#{transferMB.transFormEnabled}">
<h:outputText value="transForm"/>
</p:panelGrid>
</h:form>
<h:form id="spreadForm">
<p:panelGrid columns="1" rendered="#{transferMB.spreadFormEnabled}">
<h:outputText value="spreadForm"/>
</p:panelGrid>
</h:form>
and in your corresponding bean:
public boolean isTransFormEnabled() {
if (selectedItems.contains("1")) {
return true;
} else {
return false;
}
}
public boolean isSpreadFormEnabled() {
if (selectedItems.contains("2")) {
return true;
} else {
return false;
}
}
You should be calling Boolean-like values into your rendered attributes.
Example:
<p:panelGroup id="group" rendered="{#bean.isOneSelected}">
...
</p:panelGroup>
<p:panelGroup id="group" rendered="{#bean.isTwoSelected}">
...
</p:panelGroup>
And for getting values from selectManyMenu. Please check here.
Also the rendered tag is a Boolean like condition to tell whether a tag should be displayed. You shouldn't need to pass a parameter into that. You should be getting that information from you transferMB

Get rowIndex of rich:dataTable rows

In my JSF application, I use a rich:dataTable as follows:
<rich:dataTable id="itemTable" value="#{backingBean.itemsList}" var="i" >
<rich:column> <f:facet name="header">ItemValue</f:facet>
<h:inputText id="myId" value="#{i.value}" style="width: 30px" />
</rich:column> </rich:dataTable>
<h:commandButton id="saveB" value="Save" action="#{backingBean.doSave()}" />
Bean code of doSave:
public String doSave() {
Iterator<Item> = itemsList.iterator();
while(iter.hasNext()) {
//do something
}
}
In the doSave()-Method, i need to know the row index of the current Item, is there a way to achieve this?
While Richfaces extended data tables support a selection management, Richfaces datatables don't.
What I found the easiest way to do to retrieve a somehow selected item from a list, is to add an icon to every row. For this, put the command-Button into the data table itself:
<rich:dataTable id="itemTable" value="#{backingBean.itemsList}" var="i" >
<rich:column>
<h:inputText id="myId" value="#{i.value}" />
<h:commandButton id="saveB" action="#{backingBean.doSave}" />
</rich:column>
</rich:dataTable>
In the bean code, provide the method doSave but with an additional parameter ´ActionEvent´
public String doSave(ActionEvent ev) {
Item selectedItem = null;
UIDataTable objHtmlDataTable = retrieveDataTable((UIComponent)ev.getSource());
if (objHtmlDataTable != null) {
selectedItem = (Item) objHtmlDataTable.getRowData();
}
}
private static UIDataTable retrieveDataTable(UIComponent component) {
if (component instanceof UIDataTable) {return (UIDataTable) component;}
if (component.getParent() == null) {return null;}
return retrieveDataTable(component.getParent());
}
You see, that the ActionEvent ev provides you with the source element (UIComponent)ev.getSource(). Traverse through it until you hit the UIDataTable element and use it's row data.
Possible way two is to justgive the element as parameter with the function call:
<rich:dataTable id="itemTable" value="#{backingBean.itemsList}" var="i" >
<rich:column>
<h:inputText id="myId" value="#{i.value}" />
<h:commandButton id="saveB" action="#{backingBean.doSave(i)}" />
</rich:column>
</rich:dataTable>
and in the bean
public String doSave(Item item) {
// do stuff
}
That's not as clean, but should work with the EL, too. Hope, it helps...

Request doesn't render response in primefaces datatable

I have a datatable with search field and commandLink to sort. The commandLink that I use to trigger sorting is located not in column header but on the header of datatable. When I load my page and use only commandLink to sort everything works ok. Table sorts in two orders and I see result on my page. Problem appears when I search something in globalFilter. It also works, but after that I cant sort my table. I clear inputText of globalFilter and I cant sort table. To sum up, I see result of sorting only when I not use search field. Sort operation works but request not update the datatable. I put my code below. Maybe somebody knows how to solve it.
<ui:composition>
<p:panel header="Moje pomiary" footer="#{msgs.footer}" id="myMeasurement">
<h:form id="form" prependId="false">
<p:dataTable var="m" value="#{myMeasurementTable.measurement}" id="measureList" editable="true"
widgetVar="mTable"
emptyMessage="No files found with given criteria" filteredValue="#{myMeasurementTable.filteredMeasurement}" >
<f:facet name="header">
Sortowanie według: <p:commandLink id="sortByName" actionListener="#{myMeasurementTable.sortByName}" update="measureList">
<h:outputText value="nazwa pliku" />
</p:commandLink>
|<h:commandLink action="#{myMeasurementTable.sortByArchivisationDate}"> data archiwizacji </h:commandLink>
|<h:commandLink action="#{myMeasurementTable.sortByMeasureDate}"> data badania </h:commandLink>
<p:outputPanel styleClass="searchPanel">
<h:outputText value="Szukaj: " />
<p:inputText styleClass="globalFilter" id="globalFilter" onkeyup="mTable.filter()" style="width:150px" />
</p:outputPanel>
</f:facet>
<p:column headerText="Informacje pomiarowe" style="width:125px" filterStyle="display:none" filterBy="#{m.fileName} #{m.measureDate} #{m.place} #{m.archivisationDate}"
filterMatchMode="contains" >
<p:separator styleClass="separatorColumn"/>
Nazwa pliku: <h:outputText value="#{m.fileName}" /><br />
Data badania: <h:outputText value="#{m.measureDate}" /><br />
Data archiwzacji: <h:outputText value="#{m.archivisationDate}" /><br />
Miejscowość: <h:outputText value="#{m.place}"/> <br />
Współrzędne GPS:
</p:column>
<p:column headerText="Wykresy">
<img src="/tmp/21/myfile.xls/myfile.xls_Parametr x.png" width="150"/>
</p:column> </p:dataTable></h:form></p:panel></ui:composition>
and part of my bean
#ManagedBean(name = "myMeasurementTable")
#ViewScoped
public class myMeasurementTable implements Serializable{
private static final long serialVersionUID = -9193902657201234669L;
private List<Measurement> measurement;
private List<Measurement> filteredMeasurement;
private boolean sortAscending = true;
public myMeasurementTable() {
measurement = new ArrayList<Measurement>();
fillTable(measurement);
}
public String sortByName() {
System.out.println("naciskam sortowanie");
if (sortAscending) {
Collections.sort(measurement, new Comparator<Measurement>() {
#Override
public int compare(Measurement m1, Measurement m2) {
return m1.getFileName().compareTo(m2.getFileName());
}
});
sortAscending = false;
} else {
Collections.sort(measurement, new Comparator<Measurement>() {
#Override
public int compare(Measurement m1, Measurement m2) {
System.out.println(m2.getFileName());
return m2.getFileName().compareTo(m1.getFileName());
}
});
sortAscending = true;
}
return null;
}
Ok I found solution on primefaces forum. It's simple. I only added oncomplete="mTable.filter()" to commandButton and everything works as I want.

Dynamic Column in JSF Datatable JSF2.0

I need one help from you. I am using JSF 2.0 and I have a datatable component . One of the column in the datatable is an action column and I need to create a toolbar which contains different type of actionsource component such as command button, link etc. The type of actionsource is determined at run time and number of actionsource is also done at run time. How I can implement this in JSF 2.0
<p:dataTable value="#{listBranchBean1.rowDataModel}" var="rowItem"
id="myId" paginator="true"
paginatorTemplate="{FirstPageLink}{PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}{RowsPerPageDropdown} "
rowsPerPageTemplate="10,5,2" previousPageLinkLabel="<"
nextPageLinkLabel=">" widgetVar="branchTable"
selection="#{listBranchBean1.selectedBranchesPrime}"
resizableColumns="true"
sortBy="#{rowItem.columnsValueMap['branchId'].value}">
<f:facet name="header">
<p:outputPanel>
<h:outputText value="Search all fields:" />
<p:inputText id="globalFilter" onkeyup="branchTable.filter()"
style="width:150px" />
</p:outputPanel>
</f:facet>
<p:column selectionMode="multiple" style="text-align:left">
<f:facet name="header">
<h:outputText value="Select" />
</f:facet>
<h:outputText value="#{rowItem.uniqueId}" />
</p:column>
<p:column
rendered="#{listBranchBean1.columnsMap['objectId'].hidden==false}"
sortBy="#{rowItem.columnsValueMap['objectId'].value}"
filterBy="#{rowItem.columnsValueMap['objectId'].value}">
<f:facet name="header">
<h:outputText
value="#{listBranchBean1.columnsMap['objectId'].displayLabel}" />
</f:facet>
<h:outputText
value="#{rowItem.columnsValueMap['objectId'].value}" />
</p:column>
<p:column
rendered="#{listBranchBean1.columnsMap['actions'].hidden==false}">
<f:facet name="header">
<h:outputText
value="#{listBranchBean1.columnsMap['actions'].displayLabel}" />
</f:facet>
<p:toolbar>
<p:toolbarGroup>
<ui:repeat var="action"
value="#{rowItem.columnsValueMap['actions'].value}">
<p:commandButton title="#{action}" type="button">
</p:commandButton>
</ui:repeat>
</p:toolbarGroup>
</p:toolbar>
</p:column>
</p:dataTable>
I want to replace the last column with something like
<p:toolbar binding="#{listBranchBean1.getActions(rowItem)}">
</p:toolbar>
I appreciate your help
Prajeesh Nair
There is a difference between build-time and render-time in JSF. Build-time tags like <ui:repeat> have the ability to create new components dynamically, but they can only use data that is available at build-time.
However, using Java you are also allowed to alter the component tree programmatically, but this too can not just happen at any moment. The safe moment to do this is the preRenderViewEvent, which is a good bit later than the build-time moment (which is the restore view phase) and you should have all the data you need by then.
Inside an event handler for this event you can reference the tool bar you bound to your backing bean, and programmatically add columns to it.
For examples see:
http://balusc.omnifaces.org/2006/06/using-datatables.html#PopulateDynamicDatatable
http://arjan-tijms.omnifaces.org/2011/09/authoring-jsf-pages-in-pure-java.html
Do note that if your backing bean is #ViewScoped, you'd better not use binding but use a manual lookup instead. This is due to some bugs with respect to the view scope and binding components in JSF.
below code will create dynamic column on the basis of selected country
public void loadDynamicList() throws Exception {
int i=0;
dynamicList = new ArrayList<List<String>>();
dynamicList.add(Arrays.asList(new String[] { "ID1" }));
existingCountryList = new ArrayList<Country>();
String countryCode="US";
existingCountryList.add(getCountryService().getCountryByCode(countryCode));
Country country=getCountryService().getCountryByCode(countryCode);
countryLanguageSet=country.getCountryLanguage();
i=country.getCountryLanguage().size();
dynamicHeaders = new String[i] ;
int j=0;
for (CountryLanguage count: countryLanguageSet) {
System.out.println(count.getLanguage().getLanguageName());
dynamicHeaders[j]=count.getLanguage().getLanguageName();
j++;
}
}
public void populateDynamicDataTable() {
debugLogger.debug("populateDynamicDataTable:Enter");
// Create <h:dataTable value="#{myBean.dynamicList}" var="dynamicItem">.
HtmlDataTable dynamicDataTable = new HtmlDataTable();
dynamicDataTable.setValueExpression("value", createValueExpression("#{relationBean.dynamicList}", List.class));
dynamicDataTable.setVar("dynamicItem");
// Iterate over columns.
for (int i = 0; i < dynamicHeaders.length; i++) {
// Create <h:column>.
HtmlColumn column = new HtmlColumn();
dynamicDataTable.getChildren().add(column);
// Create <h:outputText value="dynamicHeaders[i]"> for <f:facet name="header"> of column.
HtmlOutputText header = new HtmlOutputText();
header.setValue(dynamicHeaders[i]);
column.setHeader(header);
HtmlInputText input=new HtmlInputText();
column.getChildren().add(input);
}
dynamicDataTableGroup = new HtmlPanelGroup();
dynamicDataTableGroup.getChildren().add(dynamicDataTable);
debugLogger.debug("populateDynamicDataTable:Exit");
}
public HtmlPanelGroup getDynamicDataTableGroup() throws Exception {
// This will be called once in the first RESTORE VIEW phase.
if (dynamicDataTableGroup == null) {
loadDynamicList(); // Preload dynamic list.
populateDynamicDataTable(); // Populate editable datatable.
}
return dynamicDataTableGroup;
}
public List<List<String>> getDynamicList() {
return dynamicList;
}
public void setDynamicList(List<List<String>> dynamicList) {
this.dynamicList = dynamicList;
}
public void setDynamicDataTableGroup(HtmlPanelGroup dynamicDataTableGroup) {
this.dynamicDataTableGroup = dynamicDataTableGroup;
}
public ValueExpression createValueExpression(String valueExpression, Class<?> valueType) {
FacesContext facesContext = FacesContext.getCurrentInstance();
return facesContext.getApplication().getExpressionFactory().createValueExpression(
facesContext.getELContext(), valueExpression, valueType);
}

Resources