【问题标题】:PrimeFaces 5.1 + editable dataTable + fileUpload columnPrimeFaces 5.1 + 可编辑数据表 + 文件上传列
【发布时间】:2015-08-11 01:03:29
【问题描述】:

我正在使用可编辑的<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");
        }
    }
}

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

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

我希望当用户单击复选标记(以验证更新)时,该行将显示 chemin 的新值。 上面的代码不是这样的。

看起来&lt;p:rowEditor&gt; 忽略了fileUploadListener 所做的更改。有没有办法强制行编辑考虑到 fileUploadListener 所做的更改?

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

截图:

之前的版本: 注意旧的 chemin 值:blabla13blabla.pdf

点击编辑(铅笔)图标并选择要上传的新文件后:

成功上传新文件后: 请注意,chemin 属性已更新:blabla12blabla.pdf。

验证版本后:单击复选标记图标: 请注意,chemin 属性显示旧值:blabla13blabla.pdf。

【问题讨论】:

    标签: jsf file-upload primefaces datatable


    【解决方案1】:

    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());
    }
    

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-16
      • 1970-01-01
      • 1970-01-01
      • 2016-04-17
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      相关资源
      最近更新 更多