change the datatable outputText to inputText when clicked on Edit Button - jsf

I m trying to display data in jsf datable data from the database,ans in a same row i m displaying link for Edit. Now when user will clicked on edit button then it should be inputText from outputText. Here i have done coding for that but i can't change the textbox can u please help me? Thanks in advance.
ShowData.xhtml
<h:dataTable value="#{customerdata.customerList}" var="c"
styleClass="order-table" binding="#{customerdata.dataTable}"
headerClass="order-table-header" border="1" width="100%"
rowClasses="order-table-odd-row,order-table-even-row" rows="3">
<h:column>
<h:selectBooleanCheckbox></h:selectBooleanCheckbox>
</h:column>
<h:column>
<f:facet name="heder">User ID</f:facet>
<h:inputText value="#{c.cust_id}" size="10" rendered="#{c.editable}"/>
<h:outputLabel value="#{c.cust_id}" rendered="#{not c.editable}" />
</h:column>
<h:column>
<f:facet name="heder">User Name</f:facet>
<h:inputText value="#{c.cust_name}" size="10" rendered="#{c.editable}"/>
<h:outputLabel value="#{c.cust_name}" rendered="#{not c.editable}" />
</h:column>
<h:column>
<h:commandLink value="Update" rendered="#{c.editable}" action="#{customerdata.editAction(c)}" />
<h:commandLink value="Edit" action="#{customerdata.editAction(c)}" rendered="#{not c.editable}"/>
</h:column>
<h:column>
<h:commandLink value="Delete" action="#{customerdata.deleteAction(c)}" />
</h:column>
<!-- Footer Setting -->
<f:facet name="footer">
<h:panelGroup>
<h:commandButton value="prev" action="#{customerdata.pagePrevious}"
disabled="#{customerdata.dataTable.first == 0}" />
<h:commandButton value="next" action="#{customerdata.pageNext}"
disabled="#{customerdata.dataTable.first + customerdata.dataTable.rows
>= customerdata.dataTable.rowCount}" />
</h:panelGroup>
</f:facet>
</h:dataTable>
CustomerData.java
package model;
#ManagedBean(name="customerdata")
public class CustomerData implements Serializable {
private static final long serialVersionUID = 1L;
Connection con;
Statement smt;
HtmlDataTable dataTable;
//Customer cust=new Customer();
public List<Customer> getcustomerList() throws SQLException{
//System.out.println("in getcustomerlist");
List<Customer> list= new ArrayList<Customer>();
try{
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/openid","root","root");
smt = con.createStatement();
String query="select * from jsftable";
ResultSet rs= smt.executeQuery(query);
while(rs.next()){
Customer cust = new Customer();
cust.setCust_id(rs.getInt("cust_id"));
cust.setCust_name(rs.getString("cust_name"));
cust.setHas_attachment(rs.getBoolean("has_attachment"));
System.out.println("in cusotomer data"+cust.isEditable());
//store all data into a List
list.add(cust);
}
}
catch(Exception e){
e.printStackTrace();
}
return list;
}
public void pageFirst() {
dataTable.setFirst(0);
}
public void pagePrevious() {
dataTable.setFirst(dataTable.getFirst() - dataTable.getRows());
System.out.println("Prevoius"+dataTable.getFirst());
}
public void pageNext() {
dataTable.setFirst(dataTable.getFirst() + dataTable.getRows());
System.out.println("Next"+dataTable.getFirst());
}
public void pageLast() {
int count = dataTable.getRowCount();
int rows = dataTable.getRows();
dataTable.setFirst(count - ((count % rows != 0) ? count % rows : rows));
}
public HtmlDataTable getdataTable() {
return dataTable;
}
public void setdataTable(HtmlDataTable dataTable) {
this.dataTable = dataTable;
}
public void showRow(){
System.out.println(dataTable.getRows());
}
public String deleteAction(Customer customer) throws SQLException{
//list.remove(customer);
//System.out.println(customer.cust_id);
try{
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/openid","root","root");
smt = con.createStatement();
String query="delete from jsftable where cust_id="+customer.cust_id+"";
//ResultSet rs= smt.executeQuery(query);
smt.executeUpdate(query);
}
catch(Exception e){
e.printStackTrace();
}
return null;
}
public String editAction(Customer customer) {
//list.remove(customer);
System.out.println(customer.cust_id);
customer.setEditable(true);
return null;
}
}
Customer.java
public class Customer {
int cust_id;
String cust_name;
boolean has_attachment;
boolean editable;
String edit_value;
public String getEdit_value() {
System.out.println("in getter");
return edit_value;
}
public void setEdit_value(String editvalue) {
this.edit_value = editvalue;
}
public boolean isHas_attachment() {
System.out.println("in getter of has_attach");
return has_attachment;
}
public void setHas_attachment(boolean hasAttachment) {
has_attachment = hasAttachment;
}
public int getCust_id() {
System.out.println("in getter of cust_id");
return cust_id;
}
public void setCust_id(int custId) {
cust_id = custId;
}
public String getCust_name() {
return cust_name;
}
public void setCust_name(String custName) {
cust_name = custName;
}
public boolean isEditable() {
//System.out.println("in isEditable"+editable);
return editable;
}
public void setEditable(boolean editable) {
this.editable = editable;
//System.out.println("in set editable"+editable);
}
}

To be honest, I wonder how your code works at all. It has several major flaws.
You should start with
giving your managed bean a scope, the #ViewScoped seems the most appropriate (see here)
removing the database access from the getter method. Put it inside an #PostConstruct annotated method in your bean. Getter methods can be called several times during JSF lifecycle. The #PostConstruct method only after bean construction.
closing sql statement and connection when you are done (stmt.close() and con.close())
following bean field and method naming conventions: A private field xxx has a getter getXxx and a setter setXxx (the capitalization is important)
removing datatable binding. It is not necessary here.
I recommend to go through this simple CRUD example by BalusC and adapting it for your functional requirements.

Add id tag for datatable:
<h:dataTable value="#{customerdata.customerList}" var="c" id="customerDT"
styleClass="order-table" binding="#{customerdata.dataTable}"
headerClass="order-table-header" border="1" width="100%"
rowClasses="order-table-odd-row,order-table-even-row" rows="3">
Add in your edit CommandButton update tag:
But why you don't use the inplace component using primefaces? http://www.primefaces.org/showcase-labs/ui/inplace.jsf (need a save button)

Related

Editing h:dataTable

The functionality I need is as follows:
I have a datatable with 4 columns(already works well, for the purpose of explanation I provided just one column "Price") and in the last column I have a "modify" icon. When I click on "modify" icon I would like inputText to pop-up where I can do my modifications for each column in the row.
From technical perspective I'm doing it:
In JSF:
<h:dataTable value="#{item.getItemList()}" var="c"
styleClass="order-table"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row">
<h:column>
<f:facet name="header"> Price </f:facet>
<h:inputText value="#{c.price}" size="5" rendered="#{c.editable}" />
<h:outputText value="#{c.price}" rendered="#{not c.editable}" />
</h:column>
<h:column>
<f:facet name="header"> Operation </f:facet>
<h:form>
<h:commandLink action="#{item.editAction(c)}">
<h:graphicImage library="images"
name="modifyIcon.png"
width="20"
rendered="#{not c.editable}"/>
</h:commandLink>
</h:form>
<h:form>
<h:commandLink action="#{item.removeItem(c)}">
<h:graphicImage value="resources/images/deleteIcon.png" width="20" />
</h:commandLink>
</h:form>
</h:column>
</h:dataTable>
In bean:
public String editAction(Item item) {
item.setEditable(true);
return null;
}
and in Item class:
public boolean isEditable() {
return this.editable;
}
public void setEditable(boolean editable) {
this.editable = editable;
}
Then when I click on modifyIcon.png nothing happends. I would expect input fields from the other columns to show up, but they don't. Do you have any idea where I could made a mistake?
since you don't show us where and how you load the list of items, we cannot give you one absolute answer. but here is a working example:
import java.io.Serializable;
public class TestItem implements Serializable{
private static final long serialVersionUID = -2725423502616632442L;
private int id;
private double price;
private boolean editable;
public TestItem(int id, double price, boolean editable) {
super();
this.id = id;
this.price = price;
this.editable = editable;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public boolean isEditable() {
return editable;
}
public void setEditable(boolean editable) {
this.editable = editable;
}
}
Controller:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean(name="testBean")
#SessionScoped
public class Test implements Serializable{
private static final long serialVersionUID = 2010307013874058143L;
private List<TestItem> items;
public Test(){
}
#PostConstruct
public void init(){
items = new ArrayList<TestItem>();
items.add(new TestItem(0,20.99,false));
items.add(new TestItem(1,30.90,false));
items.add(new TestItem(2,23.00,false));
items.add(new TestItem(3,15.50,false));
}
public final String setEditable(TestItem selectedItem){
selectedItem.setEditable(true);
return null;// null or your view-id
}
public final String save(){
for(TestItem i: this.getItems()){
System.out.println(i.getPrice());
i.setEditable(false);
}
return null;// null or your view-id
}
public List<TestItem> getItems() {
return items;
}
public void setItems(List<TestItem> items) {
this.items = items;
}
}
xhtml:
<h:form>
<h:dataTable id="DATA-TABLE" var="c" value="#{testBean.items}">
<h:column>
<f:facet name="header"> Name </f:facet>
<h:inputText value="#{c.price}" size="5" rendered="#{c.editable}" />
<h:outputText value="#{c.price}" rendered="#{not c.editable}" />
</h:column>
<h:column>
<f:facet name="header"> Operation </f:facet>
<h:commandButton action="#{testBean.setEditable(c)}" value="EDIT"
rendered="#{not c.editable}">
</h:commandButton>
<h:commandButton action="#{testBean.save}" value="SAVE"
rendered="#{c.editable}">
</h:commandButton>
</h:column>
</h:dataTable>
</h:form>

jsf2 make datatable row editable does show inputtext fields

I am trying to edit a datatable row with JSF2. In debugging the editAction is showing the correct row, but the outputtext is not transformed into inputtext to allow editing, There seems to be a rendering problema executing the edit action. My bean is sessionscoped and when hitting one of the buttons (edit, add, delete, cancel) the method getListaNoticias is executed as many times as there are inputfields.
My code:
historial.xhtml
<h:form>
<h:dataTable styleClass="tablaHistorial"
value="#{historialBean.listaNoticias}" var="o">
<h:column>
<f:facet name="header">Fecha</f:facet>
#{o.fecha}
</h:column>
<h:column>
<f:facet name="header">Noticia</f:facet>
<h:inputTextarea value="#{o.titulo}" rendered="#{o.editable}"/>
<h:outputText value="#{o.titulo}" rendered="#{not o.editable}" />
</h:column>
<h:column>
<h:commandButton action="#{historialBean.editAction(o)}">
<f:ajax render="#form" />
</h:commandButton>
</h:column>
<h:column>
<h:commandButton action="#{historialBean.save(o)}">
<f:ajax render="#form" execute="#form" />
</h:commandButton>
</h:column>
<h:column>
<h:commandButton action="#{historialBean.cancelarAccion(o)}">
<f:ajax render="#form" />
</h:commandButton>
</h:column>
<h:column>
<h:commandButton action="#{historialBean.borrar(o)}">
<f:ajax render="#form" />
</h:commandButton>
</h:column>
</h:dataTable>
</h:form>
historialBean class
#ManagedBean
#SessionScoped
public class HistorialBean implements Serializable {
private static final long serialVersionUID = 1L;
public List<Noticia> listaNoticias;
public HistorialBean() {
}
public String irAConsola() {
return navigationBean.redirectToLoggedIn();
public List<Noticia> getListaNoticias() {
ConexionUtil conexion = new ConexionUtil();
listaNoticias = new ArrayList<Noticia>();
listaNoticias = conexion.prepararListaNoticiasBBDDExterna();
return listaNoticias;
}
public void setListaNoticias(List<Noticia> listaNoticias) {
this.listaNoticias = listaNoticias;
}
public void editAction(Noticia noticia) {
noticia.setEditable(true);
}
public void editar(Noticia noticia) {
ConexionUtil conexion = new ConexionUtil();
conexion.editarNoticiaBBDDExterna(noticia);
noticia.setEditable(false);
}
public void borrar(Noticia noticia) {
ConexionUtil conexion = new ConexionUtil();
conexion.deshabilitarNoticiaBBDDExterna(noticia);
}
public void cancelarAccion(Noticia noticia) {
noticia.setEditable(false);
}
}
Noticia class
public class Noticia {
private String titulo;
private String fecha;
private boolean editable;
public Noticia(String titulo,String fecha) {
super();
this.titulo = titulo;
this.fecha = fecha;
}
public String getTitulo() {
return titulo;
}
public void setTitulo(String titulo) {
this.titulo = titulo;
}
public String getFecha() {
return fecha;
}
public boolean isEditable() {
return editable;
}
public void setEditable(boolean editable) {
this.editable = editable;
}
}
At the end I solved it putting the creation of the list in the bean constructor:
public HistorialBean() {
ConexionUtil conexion = new ConexionUtil();
listaNoticias = new ArrayList<Noticia>();
listaNoticias = conexion.prepararListaNoticiasBBDDExterna();
}
public List<Noticia> getListaNoticias() {
return listaNoticias;
}

CommandLink inside the datatable doesn't work in some cases

I have the CommandLink/CommandButton which is an element of the column in the dataTable. The dataTable is integrated with the lazy model. My code (not exactly my, because this is the primefaces showcase example) works perfect when the number of records in the table is divisible by the page size. For example the page size is 5 and the number of records is 60. But, when the number of records is 61, then when I reach the last record in the table, the action listener for every button is not called. I've tried to change p:commandlink to h:commandbutton/p:commandbuton. I've tried all the stackoverflow tips related to use update="#form" or immediate="true" or disable ajax requests by ajax="false", but the result is the same. For me it looks like a problem with dataTable rendering. Please look at the source code. This example is based on the primefaces showcase, I've added only a new column (this one with the commandlink).
xhtml page:
<h:form id="form">
<p:dataTable styleClass="test-class" id="data" var="car" value="#{tableBean.lazyModel}" scrollable="true" liveScroll="true" scrollRows="5" scrollHeight="200" lazy="true" >
<p:column headerText="Model">
<h:outputText value="#{car.model}" />
</p:column>
<p:column headerText="Year">
<h:outputText value="#{car.year}" />
</p:column>
<p:column headerText="Manufacturer">
<h:outputText value="#{car.manufacturer}" />
</p:column>
<p:column headerText="Color">
<h:outputText value="#{car.color}" />
</p:column>
<p:column headerText="Color">
<p:commandLink value="Test"
actionListener="#{tableBean.buttonListener()}" />
</p:column>
</p:dataTable>
</h:form>
datatable lazy model:
public class MyLazyModel extends LazyDataModel<Car> {
private List<Car> datasource;
public MyLazyModel(List<Car> datasource) {
this.datasource = datasource;
}
#Override
public Car getRowData(String rowKey) {
for(Car car : datasource) {
if(car.getModel().equals(rowKey))
return car;
}
return null;
}
#Override
public Object getRowKey(Car car) {
return car.getModel();
}
#Override
public List<Car> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,String> filters) {
//rowCount
int dataSize = datasource.size();
this.setRowCount(dataSize);
//paginate
if(dataSize > pageSize) {
try {
return datasource.subList(first, first + pageSize);
}
catch(IndexOutOfBoundsException e) {
return datasource.subList(first, first + (dataSize % pageSize));
}
}
else {
return datasource;
}
}
}
DataTable bean:
#ManagedBean
#ViewScoped
public class TableBean {
private LazyDataModel<Car> lazyModel;
private Car selectedCar;
private List<Car> cars;
public TableBean() {
populateRandomCars(cars, 60);
lazyModel = new MyLazyModel(cars);
}
public void setSelectedCar(Car selectedCar) {
this.selectedCar = selectedCar;
}
public LazyDataModel<Car> getLazyModel() {
return lazyModel;
}

Retrieve InputText value foreach row in JSF dataTable, which is not a property object

How would it be possible to retrieve an inputText value foreach row in JSF dataTable, since this data is not an attribute in the object on which we iterate in the loop.
(here 0 as default value). I can't change the Class properties (here Product)
<h:form>
<p:dataTable var="product" value="#{bean.products}">
<p:column headerText="Id">
<h:outputText value="#{product.id}" />
</p:column>
<p:column headerText="Name">
<h:outputText value="#{product.name}" />
</p:column>
<p:column headerText="Quantity">
<h:inputText size="3" value="0" />
</p:column>
</p:dataTable>
<h:commandButton value="Submit" action="#{bean.submit}"/>
</h:form>
Bean.class
#ManagedBean
...
public void submit() {
List<Product> products = this.getProducts();
for(Product product : list) {
System.out.println("Product.name : "+ Product.name );
System.out.println("Quantity : "+ ?? );
}
}
Bind it to a Map with Product (or its ID) as key.
E.g.
private List<Product> products;
private Map<Product, Long> quantities;
#EJB
private ProductService productService;
#PostConstruct
public void init() {
products = productService.list();
quantities = new HashMap<>();
}
public void submit() {
for (Product product : products) {
Long quantity = quantities.get(product);
System.out.println("Quantity: " + quantity);
}
}
// Getters (no setters necessary for those two properties)
with
<h:inputText size="3" value="#{bean.quantities[product]}" />
You can use the visitor pattern to get the values. Something like this:
table.visitTree(VisitContext.createVisitContext(faces),
new VisitCallback() {
#Override public VisitResult visit(VisitContext vc, UIComponent component) {
if (component.equals(quantity) && quantity.getValue() != null) {
cart.addItem(
(Product) table.getRowData(),
(Integer) quantity.getValue());
}
return VisitResult.ACCEPT;
}
});

Avoid loading datatable each time when i make an ajax call by clicking on each row

In JSF2 - I see my datatable reloading each time when i make an ajax call by clicking on each column row. Is there a way to stop loading each time i make an ajax call ? This creates problem by resetting my datatable to default values and i get a wrong value back at managed bean.
<h:inputText size="8" id="startDate"
value="#{contactBean.startDate}">
<f:convertDateTime pattern="MM/dd/yyyy" type="date" />
</h:inputText>
<h:outputText> - </h:outputText>
<h:inputText size="8" id="endDate" value="#{contactBean.endDate}">
<f:convertDateTime pattern="MM/dd/yyyy" type="date" />
</h:inputText>
<h:commandButton value="Filter"
actionListener="#{contactBean.loadAJAXFilterContentList}">
<f:ajax render=":form1:tableContents" />
</h:commandButton>
<h:dataTable id="tableContents"
value="#{contactBean.filterContentList}" var="crs"
binding="#{contactBean.dataTable}" border="1">
<h:column>
<f:facet name="header">
<h:outputText styleClass="contactTableHeader" value="Date/Time" />
</f:facet>
<h:commandLink action="#{contactBean.loadPreviewScreenContents(crs)}">
<h:outputText title="#{crs.dateTime}" value="#{crs.dateTime}">
<f:convertDateTime pattern="MM/dd/yyyy hh:mm a" type="date" />
</h:outputText>
<f:ajax render=":form1:previewScreen" />
</h:commandLink>
</h:column>
</h:dataTable>
<h:panelGrid id="previewScreen">
<h:outputText styleClass="PreviewHeader"
value="Preview of #{contactBean.previewCntDateTime}" />
</h:panelGrid>
So in the above case whenever i click the column it calls the filterContentList() method in my managed bean instead of calling loadPreviewScreenContents(crs) directly.
My bean is RequestScoped. I tried with SessionScope,ViewScope but these 2 scopes retain my previous states like i have other ajax functions in my page and it retains that state. So i cant use Session or ViewScopes in this case.
Is there a solution ?
Bean code:
#ManagedBean(name = "contactBean")
#RequestScoped
public class ContactManagedBean implements Serializable {
private static final long serialVersionUID = 1L;
List<ContactResponseBean> filterContentList = new ArrayList<ContactResponseBean>();
ContactRequestBean contactRequestBean = new ContactRequestBean();
ContactResponseBean crs = new ContactResponseBean();
private String logText;
HtmlDataTable dataTable;
public void setFilterContentList(List<ContactResponseBean> filterContentList) {
this.filterContentList = filterContentList;
}
public void setFilterContentList(List<ContactResponseBean> filterContentList) {
this.filterContentList = filterContentList;
}
public Date getPreviewCntDateTime() {
return previewCntDateTime;
}
public void setPreviewCntDateTime(Date previewCntDateTime) {
this.previewCntDateTime = previewCntDateTime;
}
public String getLogText() {
return logText;
}
public void setLogText(String logText) {
this.logText = logText;
}
public HtmlDataTable getDataTable() {
return dataTable;
}
public void setDataTable(HtmlDataTable dataTable) {
this.dataTable = dataTable;
}
public ContactResponseBean getCrs() {
return crs;
}
public void setCrs(ContactResponseBean crs) {
this.crs = crs;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public void loadAJAXFilterContentList() {
filterButtonAjxFlag = true;
}
public List<ContactResponseBean> getFilterContentList() {
ContactRequestBean contactRequestBean = new ContactRequestBean();
contactRequestBean.setUserId(getUserId());
contactRequestBean.setSummaryType(getSummaryType());
contactRequestBean.setStartDate(getStartDate());
contactRequestBean.setEndDate(getEndDate());
ContactRequestBeanService crbs = new ContactRequestBeanService();
filterContentList = crbs.getFilterContentList(contactRequestBean);
return filterContentList;
}
public void loadPreviewScreenContents(){
crs = (ContactResponseBean) dataTable.getRowData();
setPreviewCntDateTime(crs.getDateTime());
}
}

Resources