JSF 2.2 Table CRUD Ajax Example
In this tutorial we will show you how you can use Ajax in JSF 2.2 to manipulate table data using CRUD operations. With every operation we perform on our data we refresh only a part of our page. That way we use less network traffic which results in better overall performance of our application. We will explain in detail what’s happening on our page.
JSF 2.2 Ajax View
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<!--
using h:head will auto include your javascript resources
<h:outputScript library="javax.faces" name="jsf.js" target="body" />
-->
</h:head>
<h:body>
<h1>JSF 2.x table ajax example</h1>
<h:form id="todoForm">
<h:dataTable id="todoTable" value="#{todoBean.todoList}" var="todo">
<h:column>
<f:facet name="header">
<h:outputText value="Todo"/>
</f:facet>
<h:inputText value="#{todo.description}" rendered="#{todo.editable}" />
<h:outputText value="#{todo.description}" rendered="#{not todo.editable}" />
</h:column>
<h:column>
<h:commandLink value="Edit" action="#{todoBean.edit(todo)}" rendered="#{not todo.editable}" >
<f:ajax render="todoForm:todoTable" />
</h:commandLink>
<h:commandLink value="Save" action="#{todoBean.save(todo)}" rendered="#{todo.editable}" >
<f:ajax execute="@form" render="todoForm:todoTable" />
</h:commandLink>
</h:column>
<h:column>
<h:commandLink value="Cancel" action="#{todoBean.cancelEdit(todo)}" rendered="#{todo.editable}" >
<f:ajax render="todoForm:todoTable" />
</h:commandLink>
</h:column>
<h:column>
<h:commandLink id="remove" value="delete" action="#{todoBean.remove(todo)}"
onclick="return confirm('Are you sure?')">
<f:ajax render="todoForm:todoTable" />
</h:commandLink>
</h:column>
</h:dataTable>
<h2>Add todo to table</h2>
<h:outputLabel value="Todo: ">
<h:inputText id="todo" value="#{todoBean.description}" />
</h:outputLabel>
<h:commandButton value="Add record" action="#{todoBean.add}">
<f:ajax execute="todoForm" render="todoForm:todoTable" />
</h:commandButton>
</h:form>
</h:body>
</html>
Managed Bean
package com.memorynotfound.jsf;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@ManagedBean
@SessionScoped
public class TodoBean implements Serializable {
private List<Todo> todoList;
private String description;
@PostConstruct
public void init() {
todoList = new ArrayList<Todo>();
todoList.add(new Todo("Win the lottery"));
todoList.add(new Todo("Travel the world"));
todoList.add(new Todo("Eat amazing food"));
}
// #### getters and setters ####
public List<Todo> getTodoList() {
return todoList;
}
public void setTodoList(List<Todo> todoList) {
this.todoList = todoList;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
// #### Actions manipulating the list ####
public void add(){
todoList.add(new Todo(description));
}
public void save(Todo todo){
todoList.set(todoList.indexOf(todo), todo);
cancelEdit(todo);
}
public void edit(Todo todo){
for (Todo existing : getTodoList()){
existing.setEditable(false);
}
todo.setEditable(true);
}
public void cancelEdit(Todo todo){
todo.setEditable(false);
}
public void remove(Todo todo){
todoList.remove(todo);
}
}
Model
package com.memorynotfound.jsf;
public class Todo {
private String description;
private transient boolean editable;
public Todo(String description) {
this.description = description;
this.editable = false;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isEditable() {
return editable;
}
public void setEditable(boolean editable) {
this.editable = editable;
}
}
Deep Dive JSF 2.2 Ajax CRUD operation
Create
We submit all the values of the form in order to create a new todo entry. The execute=”todoForm” will send the form component identified by the name of the execute attribute to the server for processing. If you want to submit multiple values you can delimit all the components with a space. The render=”todoForm:todoTable” will perform a partial refresh of the page. In this case only the todoTable will be refreshed.
<h:outputLabel value="Todo: ">
<h:inputText id="todo" value="#{todoBean.description}" />
</h:outputLabel>
<h:commandButton value="Add record" action="#{todoBean.add}">
<f:ajax execute="todoForm" render="todoForm:todoTable" />
</h:commandButton>
When we receive the form submission in our Managed bean we simply add the new Todo to our todoList.
public void add(){
todoList.add(new Todo(description));
}
Read
We display the value using the el – Expression Language – #{todoBean.todoList} this expression maps to the getTodoList() method in our Managed Bean.
<h:dataTable id="todoTable" value="#{todoBean.todoList}" var="todo">
<h:column>
<f:facet name="header">
<h:outputText value="Todo"/>
</f:facet>
<h:inputText value="#{todo.description}" rendered="#{todo.editable}" />
<h:outputText value="#{todo.description}" rendered="#{not todo.editable}" />
</h:column>
</h:dataTable>
In this example we populate the list with the @PostConstruct annotation, this will execute the init() method when the bean is created.
private List<Todo> todoList;
@PostConstruct
public void init() {
todoList = new ArrayList<Todo>();
todoList.add(new Todo("Win the lottery"));
todoList.add(new Todo("Travel the world"));
todoList.add(new Todo("Eat amazing food"));
}
public List<Todo> getTodoList() {
return todoList;
}
Update
In order to update an entry in the table we first need to make the entry editable, we achieve this using a transient boolean value in our model. When this boolean is set to true we display the input field where the value can be updated and we also display the save link which when pressed will save the current entry in our table. The execute=”@form” will send the changed values to our Managed Bean method on which we will save the values.
<h:column>
<h:commandLink value="Edit" action="#{todoBean.edit(todo)}" rendered="#{not todo.editable}" >
<f:ajax render="todoForm:todoTable" />
</h:commandLink>
<h:commandLink value="Save" action="#{todoBean.save(todo)}" rendered="#{todo.editable}" >
<f:ajax execute="@form" render="todoForm:todoTable" />
</h:commandLink>
</h:column>
<h:column>
<h:commandLink value="Cancel" action="#{todoBean.cancelEdit(todo)}" rendered="#{todo.editable}" >
<f:ajax render="todoForm:todoTable" />
</h:commandLink>
</h:column>
Here are the managed bean methods for editing, updating and cancelling.
public void edit(Todo todo){
for (Todo existing : getTodoList()){
existing.setEditable(false);
}
todo.setEditable(true);
}
public void save(Todo todo){
todoList.set(todoList.indexOf(todo), todo);
cancelEdit(todo);
}
public void cancelEdit(Todo todo){
todo.setEditable(false);
}
Delete
We use the JavaScript onclick action to simply verify if the user actually wants to delete the entry.
<h:column>
<h:commandLink id="remove" value="delete" action="#{todoBean.remove(todo)}"
onclick="return confirm('Are you sure?')">
<f:ajax render="todoForm:todoTable" />
</h:commandLink>
</h:column>
We remove the entry from the list.
public void remove(Todo todo){
todoList.remove(todo);
}
Demo
URL: http://localhost:8080/jsf-table-ajaxWhen the edit button is pressed, the save and cancel links are displayed. Also the todo is changed by an input field where we can edit our table data.
When we save the edited entry we can see that the table is correctly updated.
We can also create a new entry by filling in the form.
When the add record button is pressed the new entry is created and the table is updated.
Thank you a lot! I’m using JSF 2.2 with ajax and watched through dozens of examples. But only this tutorial is full and WORKING.