在更新表格内容时,我在更新ExportToolbar时遇到了一些问题。我第一次单击CSV导出链接它工作正常,但如果表更新,我再次单击CSV链接,我得到相同的前一个表内容的导出。我将尝试显示设置以及数据如何变化。我希望有人之前已经看过这种行为并且可以把我指向正确的地方。我已经使用了wicket 9年了,从来没有像我一样陷入困境。提前感谢您的帮助。
Wicket版本7.7.0,oops no 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);
}
所以表格正在更新,我的提供商有一个像冠军一样工作的更新方法,但我似乎无法弄清楚为什么导出工具栏在第一次导出后没有更新,而我&#39 ; m担心属性模型也不会更新文件名。这很奇怪,并且似乎没有遵循通常的wicket模型更新行为。
有人出口工具栏有这样的问题,或者我做错了什么,或者没有做正确的事情?谢谢你的帮助。
(编辑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数据不被缓存?
答案 0 :(得分:1)
得到了答案,还有一些比赛。诀窍是覆盖创建导出链接并使ResourceStreamResource然后在其上设置缓存超时。 Wicket有时会伤害......
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());
}
};