У меня есть веб-приложение, которое использует dataTables в функциях JSF и Primefaces, чтобы оно могло выполнять некоторые дополнительные динамические функции. В dataTable у меня есть строки, содержащие редактируемые данные. Моя конечная цель состоит в том, чтобы пользователи могли редактировать эти данные, нажимать кнопку сохранения, и операторы обновления будут выполняться для замены того, что присутствует в базе данных. Проблема в том, что в настоящее время я не знаю, как обнаруживать изменения в объектах в списке массивов.
Я сделал пример, чтобы посмотреть, сможет ли кто-нибудь решить мою дилемму. Слушайте, у меня есть код, который создает dataTable, а в dataTable есть объекты из ArrayList, каждый объект содержит три разные строки. Объекты доступны для редактирования в datatable. Мне нужно иметь возможность как минимум получить индекс ArrayList объекта, редактируемого на странице. При этом я мог бы сформировать новый список редактируемых объектов и написать метод, который выполняет пакетное обновление только редактируемых объектов (объект в моем сценарии эквивалентен строке данных в базе данных). Мой предыдущий метод заключался в переборе всего ArrayList и обновлении всех объектов (строк), но по мере того, как список становится большим, это становится очень дорогим. Прямо сейчас у меня есть метод Primefaces onCellEdit, который сообщает мне предыдущее значение и значение, на которое оно было изменено, но нет способа точно определить, изменился ли объект. Любая помощь будет оценена по достоинству. Приведенный ниже код настроен таким образом, что его можно копировать, вставлять и выполнять.
Редактировать: В моей ситуации мне не нужно обновлять ArrayList. Это делается автоматически с использованием входных данных на страницах, а также геттера и сеттера для bean-компонента. Что мне нужно сделать, так это узнать, какие объекты (строки) редактируются, чтобы я мог отодвинуть их в сторону и выполнить обновление базы данных, где я обновляю только то, что отредактировано. ArrayList является зеркалом того, что находится в базе данных, но цель здесь состоит в том, чтобы обновить базу данных, чтобы отразить отредактированный ArrayList, без должен выполнить итерацию по всему списку.
Продукт.java
public class Prod{
private String value1;
private String value2;
private String value3;
public String getValue1() {
return value1;
}
public void setValue1(String value1) {
this.value1 = value1;
}
public String getValue2() {
return value2;
}
public void setValue2(String value2) {
this.value2 = value2;
}
public String getValue3() {
return value3;
}
public void setValue3(String value3) {
this.value3 = value3;
}
}
Listen.java
import java.io.IOException;
import java.util.ArrayList;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import org.primefaces.event.CellEditEvent;
import com.product.inventory.beans.Prod;
@ManagedBean(name = "listen")
@SessionScoped
public class Listen{
private ArrayList<Prod> products;
boolean firstEdit = true;
public Listen(){
}
public ArrayList<Prod> setup(){
ArrayList<Prod> result = new ArrayList<>();
int numObject = 100;
int iterations = 0;
while( iterations < numObject){
Prod prod = new Prod();
prod.setValue1("A" + iterations);
prod.setValue2("B" + iterations);
prod.setValue3("C" + iterations);
result.add(prod);
iterations = iterations + 1;
}
return result;
}
public void onCellEdit(CellEditEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
if (newValue != null && !newValue.equals(oldValue)) {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO,
"Cell Changed", "Old: " + oldValue + ", New:" + newValue);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
if (isFirstEdit()){
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new
FacesMessage(FacesMessage.SEVERITY_INFO,
"Note", "To confirm changes, please select 'Save Changes'
or they will not be saved.") );
this.setFirstEdit(false);
}
}
public void goTest(){
System.out.println("Initializing...");
this.products = setup();
ExternalContext ec = FacesContext.getCurrentInstance()
.getExternalContext();
try {
ec.redirect(ec.getRequestContextPath()
+ "/test.xhtml");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Table Structure Made");
}
public boolean isFirstEdit() {
return firstEdit;
}
public void setFirstEdit(boolean firstEdit) {
this.firstEdit = firstEdit;
}
public ArrayList<Prod> getProducts() {
return products;
}
public void setProducts(ArrayList<Prod> products) {
this.products = products;
}
}
test.xhtml
<!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:ui = "http://java.sun.com/jsf/facelets"
xmlns:h = "http://java.sun.com/jsf/html"
xmlns:f = "http://java.sun.com/jsf/core"
xmlns:p = "http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form id = "form" method = "post">
<p:growl id = "msgs" showDetail = "true" sticky = "false">
</p:growl>
<div >
<p:dataTable id = "products" var = "prod" value = "#{listen.products}"
scrollable = "true" scrollHeight = "900"
editable = "true" editMode = "cell" widgetVar= "prodCell">
<p:ajax event = "cellEdit" listener = "#{listen.onCellEdit}"
update = ":form:msgs"/>
<p:column filterBy = "#{prod.value1}" filterMatchMode = "contains"
style = "width: 300px;" headerText = "Name">
<p:cellEditor>
<f:facet name = "output"><h:outputText value = "#
{prod.value1}" /></f:facet>
<f:facet name = "input"><p:inputTextarea rows = "2" value = "#
{prod.value1}" style = "width: 96%"/></f:facet>
</p:cellEditor>
</p:column>
<p:column style = "width: 140px;" headerText = "Vendor">
<p:cellEditor >
<f:facet name = "output"><h:outputText value = "#
{prod.value2}" /></f:facet>
<f:facet name = "input">
<h:selectOneMenu value = "#{prod.value2}"
style = "width:100%">
<f:selectItem itemValue = "Y" itemLabel = "Yes"/>
<f:selectItem itemValue = "N" itemLabel = "No"/>
</h:selectOneMenu>
</f:facet>
</p:cellEditor>
</p:column>
<p:column style = "width: 275px;" headerText = "Version Release">
<p:cellEditor>
<f:facet name = "output"><h:outputText value = "#
{prod.value3}" /></f:facet>
<f:facet name = "input"><p:inputTextarea rows = "1" value = "#
{prod.value3}" style = "width: 96%"/></f:facet>
</p:cellEditor>
</p:column>
<f:facet name = "footer">
<div align = "left">
<p:commandButton value = "post" action = "#{tables.showChange}"
ajax = "false"></p:commandButton>
</div>
</f:facet>
</p:dataTable>
</div>
<p:contextMenu for = "products" widgetVar = "pMenu">
<p:menuitem value = "Edit Cell" icon = "pi pi-search"
onclick = "PF('prodCell').showCellEditor();return false;"/>
<p:menuitem value = "Hide Menu" icon = "pi pi-times"
onclick = "PF('pMenu').hide()"/>
</p:contextMenu>
</h:form>
Индекс.xhtml
<!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:ui = "http://java.sun.com/jsf/facelets"
xmlns:h = "http://java.sun.com/jsf/html"
xmlns:f = "http://java.sun.com/jsf/core"
xmlns:p = "http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form method = "post">
<h:commandButton value = "Contact Spreadsheet" ajax = "false"
action = "#{listen.goTest}" ></h:commandButton>
</h:form>
</h:body>
</html>
Это именно то, для чего предназначен лист PFE: Primefaces.org/showcase-ext/sections/sheet/basicUsage.jsf, когда вы редактируете каждую ячейку, он точно отслеживает, какие строки были отредактированы, поэтому вы можете точно знать, что было изменено, и просто обновить эти записи и зафиксировать их.
Спасибо, Мелловер. Я не знал, что это существует. Вопрос по листу. Когда метод sheet.getUpdates() выполняется в управляемом компоненте, содержит ли результирующий список все измененные объекты строк?
Да, лист.getUpdates содержит все строки, которые были изменены с момента последнего вызова sheet.commitUpdates(); Таким образом, вы можете контролировать, когда сбрасывать обновления.
Большое спасибо за это. Я бы принял это как ответ, если бы вы разместили его как один.
Хорошо, я разместил как решение, большое спасибо!
Решение, которое вам нужно, — это компонент Лист расширений PrimeFaces для поведения, которое вы ищете.
Лист удовлетворяет потребность, которую не удовлетворяет таблица данных PrimeFaces с редактированием в ячейке. Он может обрабатывать большой объем данных с редактированием отдельных ячеек без отправки всего листа. Знакомая навигация по электронным таблицам с помощью клавиш TAB и SHIFT+TAB, а также привычные возможности работы с электронными таблицами.
Особенности включают в себя:
На основе Handsontable от Handsoncode.
Возможно, я нашел способ решить мою проблему, но используя логику. Никаких наблюдаемых или прослушивающих методов. Если у кого-то есть возможное решение, дайте мне знать!