JSF commandbutton id inside datatable - jsf

How can I add in commandbutton inside datatable?
<hx:dataTableEx value="#{searchData.searchFriends}" var="s">
<hx:columnEx>
<f:facet name="header">
<h:outputText value="First Name" />
</f:facet>
<hx:requestLink action="#{pc_Search.doAddFriendAction}">
<h:outputText value="Add as Friend" />
<f:param name="friendId" value="#{s.memberId}" />
</hx:requestLink>
</hx:columnEx>
</hx:dataTableEx>
To get the data at backend
String friendId = (String)getRequestParam().get("friendId");
But once I change the requestlink to command button the friedId = null? any idea how can i pass value using command button

Wrap the datatable value in a DataModel. Then you can obtain the selected row by DataModel#getRowData().
public class Bean {
private List<Friend> friends;
private DataModel friendsModel;
public Bean () {
friends = getItSomehow();
friendsModel = new ListDataModel(friends);
}
public void addAsFriend() {
Friend selectedFriend = (Friend) friendsModel.getRowData();
// ...
}
}
with
<h:dataTable value="#{bean.friendsModel}" var="friend">
<h:column>
<h:commandButton value="Add as friend" action="#{bean.addAsFriend}" />
</h:column>
</h:dataTable>
Should work as good with IBM Faces Client Framework (those hx: components).

Related

How to render a datatable in JSF with AJAX clicking a commandButton

The objective is to have a h:commandButton and once I have clicked it, using AJAX it will show the datatable "listaActores" (initially not showing it).
How could i do this? I have search for a solution, but I only found how to re-render the table once is present. My current code shows the table without doing nothing and clicking the button doesn't do anything.
<h:form>
<h:commandButton id="submit" value="Submit">
<f:ajax event="click" execute="#this" render="listaActores" />
</h:commandButton>
<h:dataTable id="listaActores" border="1"
value="#{peliculasEditarBean.listaActores}" var="actor">
<h:column>
<f:facet name="header">NOMBRE</f:facet>
#{actor.nombre}
</h:column>
<h:column>
<f:facet name="header">APELLIDO</f:facet>
#{actor.apellido}
</h:column>
</h:dataTable>
</h:form>
Your question is somewhat incomplete, but I'll answear anyway. Two things:
You're not saying how the table is "initially not showing". If there is some rendered on it, than you need to know that you must render a parent of the table. You can render only things that exist in rendered HTML. See for example this answer.
If you'll put action in the button you'll see that the AJAX won't work. You need to change event to action or delete this attribute to use a default.
I preperend simple working example (BTW. Welcome on Stackoverflow :-) If you want get help faster Minimal, Reproducible Example should be your's part of a question :-)):
(XHTML, added action to commandButton and remove event in f:ajax)
<h:form>
<h:commandButton id="submit" value="Submit"
action="#{peliculasEditarBean.initialize}">
<f:ajax execute="#this" render="listaActores" />
</h:commandButton>
<h:dataTable id="listaActores" border="1"
value="#{peliculasEditarBean.listaActores}" var="actor">
<h:column>
<f:facet name="header">NOMBRE</f:facet>
#{actor.nombre}
</h:column>
<h:column>
<f:facet name="header">APELLIDO</f:facet>
#{actor.apellido}
</h:column>
</h:dataTable>
</h:form>
(and bean)
#ManagedBean
#ViewScoped
public class PeliculasEditarBean implements Serializable {
private List<Actor> listaActores = null;
public List<Actor> getListaActores() {
return listaActores;
}
public void initialize() {
listaActores = new ArrayList<>(3);
listaActores.add(new Actor("foo", "bar"));
listaActores.add(new Actor("foo", "foo"));
listaActores.add(new Actor("bar", "bar"));
}
public class Actor {
private final String nombre;
private final String apellido;
Actor(String nombre, String apellido) {
this.nombre = nombre;
this.apellido = apellido;
}
public String getApellido() {
return apellido;
}
public String getNombre() {
return nombre;
}
}
}

jsf inputText only displayed value when is readonly true or outputText

I have a h:inputText with valueChangeListener, when the user type some code another h:inputText display data from MySQL about that code, the valueChangeListener works but the second h:inputText not displayed the value and only do it when I set the readonly attribute or I change the component to h:outputText
my facelets page is:
<h:form id="idFacturacion">
<rich:panel>
<f:facet name="header">
<h:outputText value="FACTURACION AL CLIENTE" />
</f:facet>
<h:panelGrid columns="4">
<h:outputText value="Cedula: " />
<h:inputText value="#{facturaBean.encFactura.cedula}" onchange="submit();" valueChangeListener="#{facturaBean.processValueChange}" />
<h:outputText value="Nombre: " />
<h:inputText value="#{facturaBean.encFactura.nombre_cli}" />
</h:panelGrid>
</rich:panel>
</h:form>
facturaBean is:
#ManagedBean
#SessionScoped
public class FacturaBean {
private EncFactura encFactura = new EncFactura();
//getter and setter
public void processValueChange(ValueChangeEvent event){
String ced = event.getNewValue().toString();
try{
//do the database thing
if(resultSet.next()){
encFactura.setNombre_cli(resultSet.getString("nombre_cli"));
}else{
encFactura.setNombre_cli("");
}
}catch(SQLException error){
facesContext.addMessage(null, new FacesMessage("Hubo un error SQL."));
}
}
}
Please see
Change inputText value from listener method… and
Possible to execute `valueChangeListener` for `p:inputText` without hitting `enter` key?
May I suggest using ajax?
Here is a primefaces example but you could apply to richfaces..
<h:inputText value="#{facturaBean.stringOne}" >
<p:ajax event="change" listener="#{facturaBean.processValueChange}" update="strTwo"/> </h:inputText> <h:outputText value="Nombre: " />
<h:inputText id="strTwo" value="#{facturaBean.stringTwo}" />
</h:panelGrid>
private String stringOne= "";
private String stringTwo= "";
public void processValueChange(){
stringTwo = stringOne;
}
With getters etc.. basically on change, fires off to ajax, you do your database call etc, then it returns the response and updates your other input field, it's a much cleaner way than trying to submit forms etc..
Also are you sure you want session scope?

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.

JSF Cannot save change to datatable row to the database

I have a primefaces datatable. I populate it from the database. One of the fields is a boolean represented by a checkbox. I want that if I check or uncheck the checkbox, that I can save the change back to the database.
I have tried passing the current value of the row to the managed bean to save, but the new value of the checkbox isn't reflected in the current row object. How can I get the change into the current row object so I can successfully save the change to the DB?
Here is what I am doing now... I have tried to provide just what is needed. If it is too much information or too little, let me know. Thanks.
#ManagedBean(name = "itemManagerBean")
#ViewScoped
public class ItemManagerBean implements Serializable {
...
public ArrayList<Item> getAllItemsForUser() {
List list = ecf.findByPartyId(user.getPartyId());
ArrayList<Item> itemList = new ArrayList<>(list);
return (itemList);
}
...
public String saveItem(Item item){
System.out.println(item.toString());
ecf.updateRecord(item);
return (null);
}
}
//item class
public class Item {
private BigInteger itemId;
private String name;
priave boolean saleable; //database column is not null
//getters and setters
}
//facelet
<h:form>
<p:dataTable id="id_itemList"
var="item"
value="#{itemManagerBean.allItemsForUser}" >
<p:column headerText="ID">
<h:outputText value="#{item.itemId}" />
</p:column>
<p:column headerText="Name">
<h:outputText value="#{item.name}" />
</p:column>
<p:column headerText="Saleable" >
<p:selectBooleanCheckbox value="#{item.saleable}" />
</p:column>
<p:column width="15" >
<p:commandButton id="id_saveRowButton" icon="ui-icon-disk"
title="Save" action="#{itemManagerBean.saveItem(item)}"/>
</p:column>
</p:dataTable>
</h:form>
You need to create a selectedItem property in ItemManagerBean and update its value when the user clicks on the commandButton:
In ItemManagerBean
private Item selectedItem;
// getter and setter
In the xhtml page
<p:column width="15" >
<p:commandButton id="id_saveRowButton" icon="ui-icon-disk"
title="Save" action="#{itemManagerBean.saveItem}">
<f:setPropertyActionListener value="#{item}" target="#{itemManagerBean.selectedItem}" />
</p:commandButton>
</p:column>
(Note that you don't need to pass item through saveItem method. Modify saveItem in the managed bean in order to make it work with selectedItem instead of accepting an input item).
Links:
example in the PrimeFaces showcase
Passing parameter to JSF action
BalusC blog

JSF datatable: adding and removing rows clear rows values

I have a h:datatable showing a list of rows, and the fields of each row are input fields.
I render an "Add Row" button before the table, and a "Remove Row" button on each row of the table.
The baking bean is viewScoped, and the buttons add/remove elements from the java list in the backing bean, and then return to the same view.
I set the immediate attribute to "true" in the buttons in order to not validate the input fields when I add or remove a row.
Everything works ok but one thing: the values of the input fileds are cleared. I thought that the view kept the values beacuse the bean is viewScoped.
How can I achieve adding/removing rows without triggering validations and keeping the values that were already typed by the user in the form?
My view:
<h:form>
<h:commandButton value="Añadir Fila" immediate="true" action="#{tablaController.addRowAction}" />
<h:dataTable value="#{tablaController.lista}" var="fila" cellpadding="0" cellspacing="0" border="1">
<f:facet name="header">TABLA</f:facet>
<h:column>
<f:facet name="header"><h:outputLabel value="NOMBRE" /></f:facet>
<h:inputText id="nom" value="#{fila.nombre}" />
<h:message for="nom" class="msjError" />
</h:column>
<h:column>
<f:facet name="header"></f:facet>
<h:commandButton value="Quitar Fila" immediate="true" action="#{tablaController.removeRowAction(fila)}" />
</h:column>
</h:dataTable>
</h:form>
My backing bean:
#ManagedBean(name="tablaController")
#ViewScoped
public class TablaController {
private List<Fila> lista;
...
public TablaController() { }
...
#PostConstruct
public void init() {
this.lista = new ArrayList<Fila>();
for (int i=0; i<5; i++) {
Fila fila = new Fila();
fila.setNombre("");
this.lista.add(i,fila);
}
}
...
public String addRowAction () {
Fila fila = new Fila();
fila.setNombre("");
this.lista.add(fila);
return "";
}
public String removeRowAction (Fila f) {
boolean exito = this.lista.remove(f);
return "";
}
...
}
UPDATE --> MY SOLUTION:
I write here my solution if someone is interested.
The problem is that I use immediate="true" to skip validations, but this makes to skip the update_model_values too, so that the values entered by the user in the form are lost after clicking the add/remove buttons and re-redenring the page.
As I use "JSR-303 bean validation", my solution was to skip validations using the f:validateBean to enable/disable them. Depending on the button I click, if I want the validations to execute, I enable the bean validation (for example in a "submit" button), and if I want to skip them, I disable bean validation (like in the add/remove row buttons). But anyway the update_model_values always executes, so the values are not lost.
Here's the view:
<h:form>
<f:validateBean disabled="#{!empty param['disableValidation']}">
<h:commandButton value="Añadir Fila" action="#{tablaController.addRowAction}">
<f:param name="disableValidation" value="true" />
</h:commandButton>
<h:dataTable value="#{tablaController.lista}" var="fila" cellpadding="0" cellspacing="0" border="1">
<f:facet name="header">TABLA</f:facet>
<h:column>
<f:facet name="header"><h:outputLabel value="NOMBRE" /></f:facet>
<h:inputText id="nom" value="#{fila.nombre}" />
<h:message for="nom" class="msjError" />
</h:column>
<h:column>
<f:facet name="header"></f:facet>
<h:commandButton value="Quitar Fila" action="#{tablaController.removeRowAction(fila)}">
<f:param name="disableValidation" value="true" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:commandButton value="Submit" action="#{tablaController.saveData}" />
</f:validateBean>
</h:form>
The backing bean:
#ManagedBean(name="tablaController")
#ViewScoped
public class TablaController {
private List<Fila> lista;
...
public TablaController() { }
...
#PostConstruct
public void init() {
this.lista = new ArrayList<Fila>();
for (int i=0; i<5; i++) {
Fila fila = new Fila();
fila.setNombre("fila "+i);
this.lista.add(i,fila);
}
}
...
public String addRowAction () {
Fila fila = new Fila();
fila.setNombre("");
this.lista.add(fila);
return "";
}
public String removeRowAction (Fila f) {
this.lista.remove(f);
return "";
}
...
public String saveData () {
...
//processes the valid data
//for example, calls to a service method to store them in a database
...
return "";
}
...
}
I set the immediate attribute to "true" in the buttons in order to not validate the input fields when I add or remove a row.
immediate="true" is the wrong tool for the job. It should be used to prioritize validation, not to enable/disable validation. The difference is rather huge as you encountered yourself.
You want to trigger validation conditionally. In case of e.g. required="true" that'd be as easy as
<h:inputText ... required="#{saveButtonPressed}" />
where #{saveButtonPressed} evaluates true when the save button is pressed. E.g. when its client ID is present in request parameter map.
In case of JSR 303 bean validation, that'd be a matter of
<f:validateBean disabled="#{not saveButtonPressed}">
<h:inputText ... />
</f:validateBean>
or with OmniFaces <o:validateBean> which allows controlling that on a per-command basis.
<h:commandButton id="add" ...>
<o:validateBean disabled="true" />
</h:commandButton>
I had exactly the same problem. In short, you can NOT use immediate for action that update data table(UIData) or facelet repeat. Short explanation:submitted values are not kept for re-display if inputs in UIData do not go through validation. Long explanation can be found here: long explanation and a related bug in Mojarra

Resources