检票口:带有 ListView 的 FileUploadField

2024-04-04

  • 我有一个用于上传多个文件的页面。对于每个文件,用户必须指定类型和描述,这就是为什么我不能使用MultiFileUploadField...所以我用RepeatingView with a FileUploadField在每个元素以及我需要的其他两个字段中。

  • 问题是,每当单击“添加文件”按钮时(AjaxLink), the FileUploadFields已经有一个文件,被重置为空......

我能做些什么?

这里是ListView(抱歉,这不是RepeatingView but a 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);
  • The EtdDokumentRowPanel没有什么有趣的,我只是展示一个FileUploadField, a TextField对于文件描述和DropDownChoice选择文档类型(我们自己的分类)。

好吧,这有点棘手,因为 html<input type="file">任何更新后都会丢失其选择,并且真实模型对象(选择文件)FileUploadField仅当post事件发生。所以,即使我们添加AjaxEventBehavior with onchange事件进入我们的文件面板 - 用户选择文件后,它的模型将为空。

实际上,我们之前已经可以访问所选的文件了post仅从js请求,您可以实现“保存”脚本,将已选择的文件保存在某个数组中,同时处理ajax更新,然后将它们设置回来,但这很乏味。

因此,解决此问题的另一种方法是仅在新添加的组件上处理更新,而不触及其他组件。

我会用RepeatingView,因为我只需要在单击时生成新的 wicket idaddLink而不是根据模型。代码如下(仔细阅读注释):

/* 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>

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

检票口:带有 ListView 的 FileUploadField 的相关文章

随机推荐