PrimeFaces 5.1 +可编辑dataTable + fileUpload列

时间:2015-05-28 13:27:38

标签: jsf file-upload primefaces datatable

我使用的是可编辑的<p:dataTable>,其中每个<p:column>都包含<p:cellEditor>。我使用一个特定的<p:column>来表示用于存储文件名称(由用户上传)的模型项的属性(让我们称之为 chemin )。相应的<p:cellEditor>如下:

    <f:facet>中的
  • 包含<p:fileUpload><h:outputLink>
  • out <f:facet>包含<h:outputLink>

我想实现以下内容:当用户点击<p:rowEditor>(铅笔图标)时,(1)显示<p:fileUpload>,(2)然后用户选择并上传文件( 3)当用户验证更新时(通过单击复选标记),该列显示指向新上载文件的链接,这意味着当前模型项目会相应更新: chemin 属性将包含名称新上传的文件。

下面的代码正确实现了步骤(1)到(2),但步骤(3)不起作用。

Version.xhtml

<h:form id="RUDForm" enctype="multipart/form-data">
    <p:dataTable
        id="versionDT"
        var="version"
        value="#{versionController.rechercherToutVersion()}"
        editable="true"
        paginator="true"
        rows="3"
        dir="rtl"
        style="width: 100%"
        emptyMessage="#{messages.listeVide}">

        <p:ajax event="rowEdit" listener="#{versionController.updateVersion(version)}" update=":RUDForm:versionDT" />

        ...

        <p:column headerText="#{messages.chemin}">
            <p:cellEditor>
                <f:facet name="output">
                    <h:outputLink
                        id = "versionCheminLink"
                        value="#{versionController.relativeUploadUrl(version.chemin)}"
                        target="_blank"
                        rendered = "#{version.chemin != null}"
                    >
                        <h:outputText styleClass="title-text" value="#{version.chemin}"/>

                    </h:outputLink>
                </f:facet>
                <f:facet name="input">
                    <p:panelGrid
                        id="uploadUpdatePG"
                        dir="rtl"
                    >
                        <p:row>
                            <p:column>
                                <p:fileUpload
                                    id = "versionChemin"
                                    fileUploadListener="#{versionController.fileUploadListenerUpdate}"
                                    mode="advanced"
                                    dragDropSupport="false"
                                    update=":RUDForm:versionDT:uploadUpdatePG"
                                    fileLimit="1"
                                    label="#{messages.unChoix}"
                                    uploadLabel="#{messages.upload}"
                                    cancelLabel="#{messages.annuler}"
                                    invalidSizeMessage = "#{messages.invalidSizeMessage}"
                                    invalidFileMessage = "#{messages.invalidFileMessage}"
                                    sizeLimit="1000000"
                                >
                                    <f:attribute name="version" value="#{version}" />
                                </p:fileUpload>
                            </p:column>
                        </p:row>
                        <p:row>
                            <p:column>
                                <h:outputLink
                                    id = "versionCheminLinkReminder"
                                    value="#{versionController.relativeUploadUrl(version.chemin)}"
                                    target="_blank"
                                    rendered = "#{version.chemin != null}"
                                >
                                    <h:outputText styleClass="title-text" value="#{version.chemin}"/>

                                </h:outputLink>
                            </p:column>
                        </p:row>
                    </p:panelGrid>
                </f:facet>
            </p:cellEditor>
            <p:message for="versionChemin"/>
        </p:column>

        ...

        <p:column style="width:6%">
            <p:rowEditor />
        </p:column>

    </p:dataTable>
</h:form>

VersionController.java

@ManagedBean
@ViewScoped
public class VersionController extends GenericPageController implements Serializable
{

    ...

    @ManagedProperty(value="#{versionServiceImpl}")
    private VersionService versionService;
    public VersionService getVersionService() {
        return versionService;
    }
    public void setVersionService(VersionService versionService) {
        this.versionService = versionService;
    }

    private UploadedFile file;
    public UploadedFile getFile() {
        return file;
    }
    public void setFile(UploadedFile file) {
        this.file = file;
    }

    ...

    public void updateVersion(Version version)
    {
        if (getVersionService().updateVersion(version))
        {
            addInfoByKey("msgUpdateOk");
        }
        else
        {
            addErrorByKey("msgUpdateKo");
        }
    }

    ...

    public void fileUploadListenerUpdate(FileUploadEvent event)
    {
        setFile(event.getFile());
        uploadVersionUpdate((Version)event.getComponent().getAttributes().get("version"));
    }

    public void uploadVersionUpdate(Version version)
    {
        if ((getFile() != null) && (getFile().getSize() != 0))
        {
            version.setChemin(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()) + addZeros(new Random().nextInt(10),3) + getFile().getFileName());
            upload(getFile(),version.getChemin());
            addInfoByKey("RUDForm:uploadUpdatePG","uploadOk");
        }
        else
        {
            addErrorByKey("RUDForm:uploadUpdatePG","uploadKo");
        }
    }
}

我的想法是使用<f:attribute>中的<p:fileUpload>将正在编辑的模型项传递给控制器​​。

上传成功后(在方法 uploadVersionUpdate 中,由fileUploadListener调用),模型项的属性 chemin 将更新为实际文件的名称上传。

我希望当用户点击复选标记(以验证更新)时,该行将显示 chemin 的新值。 上述代码并非如此。

看起来<p:rowEditor>会忽略fileUploadListener所做的更改。有没有办法强制行版本考虑 fileUploadListener 所做的更改?

PS:文件上传工作正常(配置很好),除了 chemin 属性外,行版也能正常工作。

Screeshots:

在版本之前: Before Edition 请注意旧的 chemin 值:blabla 13 blabla.pdf

点击版本(铅笔)图标并选择要上传的新文件 After Clicking Edition (pencil) Icon and Selecting a new file to Upload

成功上传新文件后 After Successfully Uploading a new File 请注意, chemin 属性已更新:blabla 12 blabla.pdf。

验证版本后:点击复选标记图标: After validating Edition: Clicking the Check Mark Icon 请注意, chemin 属性显示旧值:blabla 13 blabla.pdf。

1 个答案:

答案 0 :(得分:0)

Solution Found Here !

填充 dataTable 值的方法是每次都调用一个服务(后者又调用一个查询数据库的存储库)。 解决方案是仅在提供 dataTable 的列表为空时才转到数据库,从而转换以下内容:

public List<Version> rechercherToutVersion()
{
  return(getVersionService().rechercherToutVersion());
}

成:

private List<Version> allVersions;

public List<Version> getAllVersions() {
  return allVersions;
}

public void setAllVersions(List<Version> allVersions) {
  this.allVersions = allVersions;
}

...

public List<Version> rechercherToutVersion()
{
  if (getAllVersions() == null)
  {
    setAllVersions(getVersionService().rechercherToutVersion());
  }
  return(getAllVersions());
}

这解决了我的问题,但即使从数据库访问的角度来看解决方案更有效,我也必须修改 saveVersion deleteVersion 方法。实际上,因为每次从数据库获取行都没有,当我删除 dataTable 中的一行时,删除的行仍然显示,如果我添加一个新项目,则该项目不会显示在 dataTable :我必须刷新页面才能看到修改。

此新问题的解决方案是“手动”删除或添加 allVersions 属性中的项目,或者只是在每次删除或<时将其重置为null em> save 已完成。删除示例:

public void deleteVersion(Version version)
{
  if (getVersionService().deleteVersion(version))
  {
    setAllVersions(null);
    addInfoByKey("msgDeleteOk");
  }
  else
  {
    addErrorByKey("msgDeleteKo");
  }
}

最后让我感到沮丧的是以下内容:为什么在原始代码版本中,更新对于其他属性非常有效,但是特别是与绑定到文件上传的属性无关?