【问题标题】:wicket ExportToolbar not refreshing on table updatewicket ExportToolbar 未在表更新时刷新
【发布时间】:2017-07-24 23:12:03
【问题描述】:

更新表格内容时,我在更新 ExportToolbar 时遇到了一些问题。我第一次单击 CSV 导出链接时它工作正常,但是如果表已更新并再次单击 CSV 链接,我会导出相同的先前表内容。我将尝试展示设置,以及数据如何变化。我希望有人以前见过这种行为,并能指出我正确的地方。我已经使用 wicket 9 年了,从来没有像现在这样陷入困境。提前感谢您的帮助。

Wicket 版本 7.7.0,哎呀,没有 7.4.0(编辑 1),抱歉

这里是表的定义:

    //main report table init:
    List<ReportRow> records = db.getVisitCountsByGrouping( getSelectedMonth());
    mainProvider = new SearchProvider<>( records, "id" );
    mainProvider.setSummationRow(sumRow);
    this.mainColumns = new ArrayList<>();
    //...columns added....
    mainTable = new DefaultDataTable<ReportRow,String>("mainTable", mainColumns, mainProvider, 25);
    mainTable.setOutputMarkupId(true);
    rft = new ReportFooterToolbar(mainTable, sumRow, this);
    rft.setOutputMarkupId(true);
    mainTable.addBottomToolbar(rft);
    exportToolbar = new ExportToolbar(mainTable, new PropertyModel<String>(this,"mainTableExportFileName"));
    exportToolbar.addDataExporter(new CSVDataExporter());
    mainTable.addBottomToolbar(exportToolbar);
    add(mainTable);

这里是更新的 Ajax 调用者:

    Form form = new Form("form");
    ArrayList<String> months = new ArrayList<>();
    months.add("January");
    months.add("February");
    months.add("March");
    months.add("April");
    months.add("May");
    months.add("June");
    months.add("July");
    months.add("August");
    months.add("September");
    months.add("October");
    months.add("November");
    months.add("December");
    DropDownChoice<String> selectMonth = new DropDownChoice<String>("selectMonth", new PropertyModel<String>(this, "selectedMonth"), months);
    selectMonth.add(new AjaxFormComponentUpdatingBehavior("change") {
        @Override
        protected void onUpdate(AjaxRequestTarget target) {
           updateMainTable(target);
        }
    });
    form.add(selectMonth);
    add(form);

方法updateMainTable(target):

public void updateMainTable( AjaxRequestTarget target ) { List<ReportRow> records = db.getVisitCountsByGrouping( getSelectedMonth()); mainProvider.update(records); target.add(rft); target.add(mainTable);
}

所以表格更新得很好,我的提供者有一个更新方法,就像一个冠军,但我似乎无法弄清楚为什么在第一次导出后导出工具栏没有更新,我担心属性模型也没有更新文件名。这很奇怪,似乎没有遵循通常的检票口模型更新行为。

有没有人在导出工具栏上遇到过这样的问题,或者我做错了什么,或者没有正确做某事?感谢您的帮助。

(编辑 1):还添加了搜索提供程序的来源:

public class SearchProvider<T> extends SortableDataProvider {
private List<T> list = null;
private ReportRow sumRow = null;

@SuppressWarnings("unchecked")
public SearchProvider( List<T> listOfStuffs, String sortColumn ) { 
    this(listOfStuffs, sortColumn, true);
}

    @SuppressWarnings("unchecked")
public SearchProvider( List<T> listOfStuffs, String sortColumn, boolean ascendingFlag ) { 
    if( listOfStuffs == null ) 
        listOfStuffs = new ArrayList<>();
    this.list = listOfStuffs;
    setSort(sortColumn, (ascendingFlag?SortOrder.ASCENDING:SortOrder.DESCENDING) );
}

public void update( List<T> listOfStuffs ) {
    if( listOfStuffs == null ) 
        listOfStuffs = new ArrayList<>();
    this.list = listOfStuffs;
            if( sumRow != null ) {
                //update sums
                sumRow.resetSums();
                for( T t : list ){
                    sumRow.add((ReportRow)t);
                }
            }

}

private SortableDataProviderComparator comparator = new SortableDataProviderComparator();

public void setSummationRow(ReportRow sumRow) {
    this.sumRow = sumRow;
    sumRow.resetSums();
    for( T t : this.list ){
        sumRow.add((ReportRow)t);
    }
}
class SortableDataProviderComparator implements Comparator<T>, Serializable {
    @SuppressWarnings("unchecked")
    public int compare( final T b1, final T b2 ) {
        PropertyModel<Comparable> c1 = new PropertyModel<Comparable>(b1, getSort().getProperty().toString());
        PropertyModel<Comparable> c2 = new PropertyModel<Comparable>(b2, getSort().getProperty().toString());

        if( c1.getObject() == null && c2.getObject() == null ) return 0;
        if( c1.getObject() == null ) return 1;
        if( c2.getObject() == null ) return -1;
        int result = c1.getObject().compareTo( c2.getObject() );
        if( !getSort().isAscending() ) result *= -1;
        return result;
    }
}

public Iterator<T> iterator( final long first, final long count ) {
    Collections.sort( this.list, comparator );
    return this.list.subList( (int)first, (int)(first+count) ).iterator();
}

public IModel<T> model( final Object o ) {
    return new AbstractReadOnlyModel<T>() {
        @Override
        @SuppressWarnings("unchecked")
        public T getObject() { return (T) o; }
    };
}

public long size() { return list.size(); }

}

(编辑 2)另一个更新:我在 ExportToolbar.onConfigure() 方法中添加了一些日志记录,以确保我的提供程序正常工作并且一切正常,问题可能出在 CSVDataExporter 本身吗?

这是我的调试日志和输出:

exportToolbar = new ExportToolbar(mainTable, new PropertyModel<String>(this,"mainTableExportFileName")) {
        @Override
        protected void onConfigure() {
            super.onConfigure();
            //setFileNameModel( new Model<String>( getMainTableExportFileName() ));
            if( getFileNameModel() != null )
                logger.debug("ExportToolbar file name model: "+ getFileNameModel().toString() +" file name: "+ getFileNameModel().getObject() );

            Iterator it = getTable().getDataProvider().iterator(0, getTable().getDataProvider().size());
            while( it.hasNext() ) {
                ReportRow r = (ReportRow) it.next();
                logger.debug("ExportToolbar data: "+ r.getCategory() +" "+ r.get1() +" "+ r.get2() + " "+ r.get3() );
            }
        }
    };

日志文件:

2017-03-06 12:28:52 DEBUG ReportPanel:244 - ExportToolbar file name model: Model:classname=[org.apache.wicket.model.PropertyModel]:nestedModel=[[ReportPanel [Component id = panel]]]:expression=[mainTableExportFileName] file name: 2017-January-AllVisits-ByReason
    2017-03-06 12:28:52 DEBUG ReportPanel:249 - ExportToolbar data: add/drop 0 38 63
    2017-03-06 12:28:52 DEBUG ReportPanel:249 - ExportToolbar data: withdraw 0 0 0
    2017-03-06 12:28:52 DEBUG ReportPanel:249 - ExportToolbar data: audit 0 0 3
    2017-03-06 12:28:52 DEBUG ReportPanel:249 - ExportToolbar data: advising 0 27 35
    2017-03-06 12:28:52 DEBUG ReportPanel:249 - ExportToolbar data: prospective 0 2 0
    2017-03-06 12:28:52 DEBUG ReportPanel:249 - ExportToolbar data: other 0 19 38
    2017-03-06 12:29:26 DEBUG ReportPanel:244 - ExportToolbar file name model: Model:classname=[org.apache.wicket.model.PropertyModel]:nestedModel=[[ReportPanel [Component id = panel]]]:expression=[mainTableExportFileName] file name: 2017-February-AllVisits-ByReason
    2017-03-06 12:29:26 DEBUG ReportPanel:249 - ExportToolbar data: add/drop 3 5 1
    2017-03-06 12:29:26 DEBUG ReportPanel:249 - ExportToolbar data: withdraw 0 1 0
    2017-03-06 12:29:26 DEBUG ReportPanel:249 - ExportToolbar data: audit 0 3 4
    2017-03-06 12:29:26 DEBUG ReportPanel:249 - ExportToolbar data: advising 8 6 6
    2017-03-06 12:29:26 DEBUG ReportPanel:249 - ExportToolbar data: prospective 3 1 2
    2017-03-06 12:29:26 DEBUG ReportPanel:249 - ExportToolbar data: other 8 8 7

(编辑 3)我能够正确更新文件名属性模型并始终使表导出链接正常工作,但我仍然遇到问题,但我能够通过创建此导出链接来保持一致表再次更新和 addOrReplace(mainTable) 而不是更新它。这就是我能够让 createExportLink() 方法再次运行的方式,否则它只会在创建 ExportToolbar 时发生,并且再也不会发生。所以现在,假设 ExportToolbar 看起来像这样:

exportToolbar = new ExportToolbar(mainTable, new PropertyModel<String>(this,"mainTableExportFileName") ) {
        @Override
        protected Component createExportLink(String componentId, final IDataExporter dataExporter ) {
            logger.debug("createExportLink: "+ componentId +" exporter: "+ dataExporter.toString());
            Component component = super.createExportLink(componentId, dataExporter);
            return component;
        }
    };      
    exportToolbar.addDataExporter(new CSVDataExporter() );

现在的诀窍似乎是,如果我在浏览器中删除历史记录并单击链接,一切都会正常工作,但否则动态更改表格并选择链接会为我提供上次单击链接时的数据。所以看起来链接被缓存了。我正在渗透组件创建,如何更改组件以确保不缓存 csv 数据?

【问题讨论】:

  • 我认为该错误必须在 SearchProvider 类中。 CSVDataExporter 在其#exportData() 方法中使用dataProvider。你确定你使用 7.7.0 吗?它尚未发布。
  • 您能否发布您的 SearchProvider 类源代码(主要是方法 iterator() 和 update(records)。您似乎在某处有错误。文件名可能不会更新,因为我看不到在哪里你更新它。你使用一个属性模型,所以我希望你的页面上有一个属性mainTableExportFileName。我进一步期望,你在你的updateMainTable方法中改变它,但你没有。
  • 不知道为什么我输入了 7.7.0,我使用的是 7.4.0,我应该压缩搜索提供程序以提高可读性。感谢您的耐心等待。

标签: wicket


【解决方案1】:

得到了答案,玩了一些。诀窍是覆盖创建导出链接并使 ResourceStreamResource 然后在其上设置缓存超时。检票口有时会痛....

        exportToolbar = new ExportToolbar(mainTable, new PropertyModel<String>(this,"mainTableExportFileName"), new AbstractReadOnlyModel<String>() {
        @Override
        public String getObject() { return getMainTableExportFileName(); } 
    }) {
        @Override
        protected Component createExportLink(String componentId, final IDataExporter dataExporter ) {
            ResourceStreamResource resource = new ResourceStreamResource() {
                @Override
                protected IResourceStream getResourceStream() {
                    return new DataExportResourceStreamWriter(dataExporter, getTable());
                }
            };
            resource.setFileName(getFileNameModel().getObject() + "." + dataExporter.getFileNameExtension());
            resource.setCacheDuration(Duration.ONE_SECOND);
            return new ResourceLink<Void>(componentId, resource).setBody(dataExporter.getDataFormatNameModel());
        }
    };      

【讨论】:

    猜你喜欢
    • 2013-12-03
    • 1970-01-01
    • 2011-05-20
    • 2012-09-24
    • 1970-01-01
    • 2011-11-13
    • 1970-01-01
    • 2014-10-03
    • 1970-01-01
    相关资源
    最近更新 更多