Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataTable - RowEditor : validation error + sort cause rows data swap #4186

Closed
tefron opened this issue Oct 31, 2018 · 3 comments
Closed

DataTable - RowEditor : validation error + sort cause rows data swap #4186

tefron opened this issue Oct 31, 2018 · 3 comments
Labels
🐞 defect Bug...Something isn't working workaround A workaround has been provided
Milestone

Comments

@tefron
Copy link

tefron commented Oct 31, 2018

1) Environment

2) Expected behavior

Rows should never swap data when sorting. This is a very subtle bug that is not caught by the user until much latter when it is hard to correct and potentially bad concurrences occurred.

3) Actual behavior

DataTable + RowEditor + validation error + sort swap rows data
..

4) Steps to reproduce

  1. run the attached project
  • there is also a doc file, 'dataTableRowEditorValidationErrorSortRowSwapDescription.doc' with images which shows the steps to reproduce.
  1. Edit first row enter invalid value in the year and accept
  2. Sort by clicking the BRAND column header and edit the first row again
  3. You can see that the first row is now Audi but it copied the ID and YEAR from the BMW.

primefaces-test-master.zip

..

5) Sample XHTML

<title>Facelet Title</title>
            <p:column style="width:32px">
                <p:rowEditor />
            </p:column>
            <p:columns value="#{dtColumnsView.columns}" var="column" columnIndexVar="colIndex" sortBy="#{car[column.property]}">
                <f:facet name="header">
                    <h:outputText value="#{column.header}" />
                </f:facet>
                <p:cellEditor>
                    <f:facet name="output"><h:outputText value="#{car[column.property]}" /></f:facet>
                    <f:facet name="input">
                        <p:inputText id="inputTextID" value="#{car[column.property]}" style="width:100%" label="#{car[column.property]}"/>
                    </f:facet>
                </p:cellEditor>
            </p:columns>


        </p:dataTable>
    </h:form>    
</h:body>

6) Sample bean

/*

  • To change this license header, choose License Headers in Project Properties.
  • To change this template file, choose Tools | Templates
  • and open the template in the editor.
    */
    package org.primefaces.test;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
//import org.primefaces.showcase.domain.Car;
//import org.primefaces.showcase.service.CarService;

@ManagedBean(name = "dtColumnsView")
@ViewScoped
public class ColumnsView implements Serializable {

private final static List<String> VALID_COLUMN_KEYS = Arrays.asList("id", "brand", "year", "color", "price");

private String columnTemplate = "id brand year";

private List<ColumnModel> columns;

private List<Car> cars;

private List<Car> filteredCars;

@ManagedProperty("#{carService}")
private CarService service;

@PostConstruct
public void init() {
    cars = service.createCars(10);

    createDynamicColumns();
}

public List<Car> getCars() {
    return cars;
}

public List<Car> getFilteredCars() {
    return filteredCars;
}

public void setFilteredCars(List<Car> filteredCars) {
    this.filteredCars = filteredCars;
}

public void setService(CarService service) {
    this.service = service;
}

public String getColumnTemplate() {
    return columnTemplate;
}

public void setColumnTemplate(String columnTemplate) {
    this.columnTemplate = columnTemplate;
}

public List<ColumnModel> getColumns() {
    return columns;
}

private void createDynamicColumns() {
    String[] columnKeys = columnTemplate.split(" ");
    columns = new ArrayList<ColumnModel>();

    for (String columnKey : columnKeys) {
        String key = columnKey.trim();

        if (VALID_COLUMN_KEYS.contains(key)) {
            columns.add(new ColumnModel(columnKey.toUpperCase(), columnKey));
        }
    }
}

public void updateColumns() {
    //reset table state
    UIComponent table = FacesContext.getCurrentInstance().getViewRoot().findComponent(":form:cars");
    table.setValueExpression("sortBy", null);

    //update columns
    createDynamicColumns();
}

static public class ColumnModel implements Serializable {

    private String header;
    private String property;

    public ColumnModel(String header, String property) {
        this.header = header;
        this.property = property;
    }

    public String getHeader() {
        return header;
    }

    public String getProperty() {
        return property;
    }
}

}
/*

  • To change this license header, choose License Headers in Project Properties.
  • To change this template file, choose Tools | Templates
  • and open the template in the editor.
    */
    package org.primefaces.test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
//import org.primefaces.showcase.domain.Car;

@ManagedBean(name = "carService")
@ApplicationScoped
public class CarService {

private final static String[] colors;

private final static String[] brands;

static {
    colors = new String[10];
    colors[0] = "Black";
    colors[1] = "White";
    colors[2] = "Green";
    colors[3] = "Red";
    colors[4] = "Blue";
    colors[5] = "Orange";
    colors[6] = "Silver";
    colors[7] = "Yellow";
    colors[8] = "Brown";
    colors[9] = "Maroon";

    brands = new String[10];
    brands[0] = "BMW";
    brands[1] = "Mercedes";
    brands[2] = "Volvo";
    brands[3] = "Audi";
    brands[4] = "Renault";
    brands[5] = "Fiat";
    brands[6] = "Volkswagen";
    brands[7] = "Honda";
    brands[8] = "Jaguar";
    brands[9] = "Ford";
}

public List<Car> createCars(int size) {
    List<Car> list = new ArrayList<Car>();
    for (int i = 0; i < size; i++) {
        list.add(new Car("id" + String.valueOf(i), brands[i], 2000 + i, colors[i], 100000 + i * 10, getRandomSoldState()));

// list.add(new Car(getRandomId(), getRandomBrand(), getRandomYear(), getRandomColor(), getRandomPrice(), getRandomSoldState()));
}

    return list;
}

private String getRandomId() {
    return UUID.randomUUID().toString().substring(0, 8);
}

private int getRandomYear() {
    return (int) (Math.random() * 50 + 1960);
}

private String getRandomColor() {
    return colors[(int) (Math.random() * 10)];
}

private String getRandomBrand() {
    return brands[(int) (Math.random() * 10)];
}

public int getRandomPrice() {
    return (int) (Math.random() * 100000);
}

public boolean getRandomSoldState() {
    return (Math.random() > 0.5) ? true : false;
}

public List<String> getColors() {
    return Arrays.asList(colors);
}

public List<String> getBrands() {
    return Arrays.asList(brands);
}

}

@tandraschko tandraschko added the 🐞 defect Bug...Something isn't working label Oct 31, 2018
@tefron
Copy link
Author

tefron commented Oct 31, 2018

I also tried to add:

<p:ajax event="sort" skipChildren="false"/>

and it made no difference.

@tefron
Copy link
Author

tefron commented Nov 5, 2018

Adding:

<p:ajax event="sort" resetValues="true"/>

Fix the swapping issue. However, it may not be desirable to lose all unsaved values when sorting the table

@melloware melloware added the workaround A workaround has been provided label Dec 29, 2020
@melloware
Copy link
Member

Can't reproduce with PF11 so this issue looks like its resolved:
pf-4186.zip

@melloware melloware added this to the 11.0.0 milestone May 4, 2022
@melloware melloware modified the milestones: 11.0.0.Final, 11.0.0 Jan 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐞 defect Bug...Something isn't working workaround A workaround has been provided
Projects
None yet
Development

No branches or pull requests

3 participants