Wicket:带ListView的FileUploadField

时间:2014-10-28 09:14:19

标签: java file-upload wicket

  • 我有一个用于上传多个文件的页面。对于每个文件,用户必须指定类型和描述,这就是我无法使用MultiFileUploadField的原因...所以我在每个元素中使用RepeatingViewFileUploadField以及我需要的其他两个领域。

  • 问题在于,只要点击“添加文件”按钮(AjaxLink),已经有文件的FileUploadFields就会重置为空...

我该怎么办?

以下是ListView(抱歉,它不是RepeatingView而是ListView):

IModel<List<EtdDokument>> listModel = getListModel();
ListView<EtdDokument> dokumenteList = new ListView<EtdDokument>("dokumenteList", listModel) {

    private static final long serialVersionUID = 1L;

    @Override
    protected void populateItem(ListItem<EtdDokument> item) {
        final boolean showHeaders = ((getList() == null) || getList().size() == 0);

        final WebMarkupContainer headRow = new WebMarkupContainer("headRow");
        headRow.setVisible(showHeaders);
        item.add(headRow);

        EtdDokumentRowPanel etdDokumentRow = new EtdDokumentRowPanel("bodyRow", item.getModel());
        item.add(etdDokumentRow);

    }
};
dokumenteList.setReuseItems(true);
add(dokumenteList);

AjaxLink<Void> addLink = new AjaxLink<Void>("addDokument") {

    private static final long serialVersionUID = 1L;

    @Override
    public void onClick(AjaxRequestTarget target) {
        EtdConfiguration etdConfig = EtdConfigForm.this.getModelObject();
        final EtdDokument newValue = new EtdDokument(etdConfig);
        tempEtdDokumente.add(newValue);
        target.addComponent(EtdConfigForm.this);
    }
};
add(addLink);
  • EtdDokumentRowPanel没有什么有趣的,我只显示FileUploadFieldTextField表示文件说明,DropDownChoice表示选择文档类型(我们自己的分类) )。

1 个答案:

答案 0 :(得分:2)

好吧,这有点棘手,因为html&#39; <input type="file">在任何更新后失去了它的选择,FileUploadField的真实模型对象(选择文件)是仅在post事件发生时设置。因此,即使我们将AjaxEventBehavior onchange事件添加到我们的文件面板中,用户选择文件后它的模型也会为空。

实际上,我们只能在post请求来自js之前访问所选文件,您可以实施“保存”#39;脚本,在某些数组中保存已选择的文件,同时执行ajax更新,然后将它们设置回来,但这很繁琐。

因此,解决此问题的另一种方法是仅对新添加的组件进行更新,而不要触及其他组件。

我将使用RepeatingView,因为只有在我点击addLink而不是根据模型时才需要生成新的wicket ID。这是代码(仔细阅读评论):

/* Method, which init your form */
private void init()
{
    /* Container, which will hold all FileUploadFields,
       as RepeatingView adds children to it's parent object. */
    WebMarkupContainer container = new WebMarkupContainer("container");

    /* We need DOM id for container component. */
    container.setOutputMarkupId(true);
    add(container);

    final RepeatingView rv = new RepeatingView("dokumenteList");
    container.add (rv);

    /* We need to add all default model values by ourselfs for RepeatingView: */
    for(EtdDokument doc : getListModel().getObject())
    {
        createDocumentRow(rv, doc);
    }

    final AjaxLink<String> addLink = new AjaxLink<String>("addDokument") {
        @Override
        public void onClick(AjaxRequestTarget target) {
            final EtdDokument newValue...;
            final EtdDokumentRowPanel r = createDocumentRow(rv, newValue);

            ...

            /* This is it. We dynamicly adding created earlier component to markup.
               This allows us to update this component via ajax. */
            target.prependJavaScript(
                    "var item=document.createElement('div');" + //creating empty 'div' tag
                    "item.id='" + r.getMarkupId() + "'; " + // set markup id for this 'div'.
                    "Wicket.$('" + container.getMarkupId() + "').appendChild(item);" // add this 'div' as container child.
            );

            /* Added 'div' is still empty, but this update will replace
               it, by real component's markup.*/
            target.add(r);
        }
    };
    add(addLink);
}

/* This method creates new instance of EDRowP (with random id) and adds
   it to RepeatingView. 
   I have dropped the implementation of your headRow, but you can include it 
   into the EDRowPanel or implement something similar. 
*/
private EtdDokumentRowPanel createDocumentRow( RepeatingView rv, EtdDokument doc )
{
    EtdDokumentRowPanel row = new EtdDokumentRowPanel(rv.newChildId(), doc);
    rv.add(row);
    return row;
}

在标记中:

<form...>
    ...
    <div wicket:id="container">
        <div wicket:id="dokumenteList"></div>
    </div>
    <a href wicket:id="addDokument">Add</a>
    ....
</form>

对于小问题来说,这看起来太麻烦了,但我认为,没有更优雅的解决方案(或者现在可能我太困了,看看它)。这应该有用。