0
votes

I have Search form. After clicking on Search button data refreshes, but dataTable columns not (columns get refreshed only on second button click). Apparently I am doing something wrong. Dynamic column code is inspired by PrimeFaces Showcase

myForm.xhtml:

<h:form id="MY_FORM">
    #{myBean.initBean()}
    ...
    <h:panelGrid id="main">
        <h:panelGrid id="buttons">
            <p:commandButton id="submitSearch"
                             value="#{msg['button.execute']}"
                             actionListener="#{myBean.submitSearch}"
                             update="resultPanel"/>
        </h:panelGrid>
    </h:panelGrid>

    <h:panelGrid id="resultPanel" border="0">
        <p:dataTable id="resultTable" var="result" value="#{myBean.searchResults}">
            <p:columns value="#{myBean.columns}" var="column" columnIndexVar="colIndex">
                <f:facet name="header">
                    <h:outputText value="#{column.header}" />
                </f:facet>
                <h:outputText value="#{result[column.property]}" />
            </p:columns>
        </p:dataTable>
    </h:panelGrid>
</h:form>

I've called column calculation method createColumns() from myBean.initBean() and myBean.submitSearch() with the same result (I see it works correctly from debugger).

@ManagedBean("myBean")
@Scope(value = "session")
public class MyBean {
    private ArrayList<HashMap<String,Object>> searchResults;
    private List<ColumnModel> columns;
    ...
    public void initBean() {
        ...
        createColumns(selectedDates);
    }

    public void submitSearch() {
        ...
        ArrayList<HashMap<String, Object>> results = prpRepository.getSearchResultByParams(searchParams);
        createColumns(selectedDates);
    }

    private void createColumns(ArrayList<String> selectedDates){
        columns = new ArrayList<ColumnModel>();   
        columns.add(new ColumnModel("Name", "NAME"));
        columns.add(new ColumnModel("Amount", "AMOUNT"));

        for (int i = 0; i < selectedDates.size(); i++) {
            columns.add(new ColumnModel(selectedDates.get(i), "DATE" + i));
        }

        setColumns(columns);
    }

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

    public void setColumns(List<ColumnModel> columns) {
        this.columns = columns;
    }
}

Additional information: I am using:

  • Oracle's Implementation of the JSF 2.1 Specification
  • JavaServer Pages API 2.2
  • Springframework 3.1.2 (incl. spring-context, spring-web)
  • Glassfish Javax.annotation 3.1.1
2
Do you have any error log? Glancing over the code, perhaps the issue is the type of searchResults. In the example, it's working with an object list (car) while you're using a hashmap list. In your datatable, the var attribute is a hashmap, isn't it? - Miguel
Yes, it is a HashMap. I don't have any errors in log, also I am getting correct table data on first Search button click. On second click also Columns are correct (just added createColumns() method to my question). - Darkwing
Is this real code? <h:form id="MY_FORM">#{myBean.initBean()}</h:form>? This doesn't make sense. Get rid of it and use a @PostConstruct annotated method as shown here: stackoverflow.com/questions/5765853/… And make sure the bean is view scoped. Perhaps it solves all side effects of doing this. - BalusC
Thanks. I've changed the code as you recommended and result is the same - Darkwing
To generate better answers sooner, carefully read stackoverflow.com/tags/jsf/info For instance, it's nowhere clear from the question when exactly you're calling createColumns(). It would make sense if you do that after you have obtained selectedDates somehow, most likely in submitSearch(). If you're creating columns before you've obtained selectedDates, then well, there would logically indeed be no columns in first place. - BalusC

2 Answers

1
votes

The problem is that columns is calculted only once time in the org.primefaces.component.datatable.DataTabe

public List<UIColumn> getColumns() {
       // if(columns == null) {     
            columns = new ArrayList<UIColumn>();
            FacesContext context = getFacesContext();
            char separator = UINamingContainer.getSeparatorChar(context);            
            for(UIComponent child : this.getChildren()) {
                if(child instanceof Column) {
                    columns.add((UIColumn) child);
                }
                else if(child instanceof Columns) {
                    Columns uiColumns = (Columns) child;                    
                    String uiColumnsClientId = uiColumns.getClientId(context);
                    uiColumns.updateModel(); /* missed code */
                    for(int i=0; i < uiColumns.getRowCount(); i++) {
                        DynamicColumn dynaColumn = new DynamicColumn(i, uiColumns);
                        dynaColumn.setColumnKey(uiColumnsClientId + separator + i);
                        columns.add(dynaColumn);
                    }
                }
            }
       // }        
        return columns;
    }

You could comment it and overwrite the class file, or find the DataTable object and setColumns to NULL inside the createColumns method

-1
votes

Finally I've worked better with debugger and found an answer. Solution was to put createColumns() method call into columns getter getColumns() as it is called automatically before submitSearch(). My problem was in application lifecycle understanding.