【问题标题】:Implementing item edition page in JSF在 JSF 中实现项目编辑页面
【发布时间】:2009-11-28 13:59:06
【问题描述】:

我正在创建一个 JSF 应用程序。我有一些来自数据库的项目(例如产品),我想创建一个 JSF 页面来编辑特定项目,即:

  • 它应该显示选定的项目属性并允许用户编辑它们,
  • 我希望能够通过一些链接查看此项目,
  • 我希望 JSF 以某种方式记住我正在编辑特定项目(例如,在编辑其数据后它应该显示该项目页面)

我在存储/传递正在编辑的项目的 ID 时遇到问题。我看到在示例 JSF CarDemo 应用程序中,它们存储在会话中查看的项目(汽车)。我不想这样做,因为我希望用户能够在单独的浏览器选项卡中编辑不同的元素。

我尝试了几种方法:

  • 在URL中使用了一些(例如itemId)GET参数,但是编辑数据后很难返回项目页面(faces-config.xml中的to-view-id字段只能包含常量),
  • 使用一些支持 bean 托管属性并在每个超链接和表单中传递其值(通过添加隐藏字段)

我仍然无法消除的问题是,如果在编辑某些项目属性后我尝试保存它们并且验证(例如f:validateLength)失败,则重新加载页面但正在编辑的项目的 ID 丢失。我认为在创建 Web 应用程序(例如用户版、商店产品版)时这是相当标准的任务,因此肯定应该有一些解决方案。

提前致谢。

【问题讨论】:

    标签: java jsf


    【解决方案1】:

    相关信息:

    请参阅this answer 以获取允许在保留 ID 的同时进行编辑的示例代码(如果您使用 JSP 而不是 Facelets,该信息应该仍然适用)。请参阅this answer 了解更多您可能想要使用的技术。有关在 URL 中保留参数的选项,请参阅 this answer


    要解决您的问题,请创建一个请求范围 bean 来执行操作:

    //pseudo-stubs
    //request scope: #{editor}
    public class Editor {
      public Integer getId();
      public void setId(Integer id);
      public String save();
    }
    

    (您可以根据需要添加其他属性。)

    通过faces-config中的注入导航到页面时,从请求参数中填充id:

    <managed-bean>
      <managed-bean-name>editor</managed-bean-name>
      <managed-bean-class>foo.Editor</managed-bean-class>
      <managed-bean-scope>request</managed-bean-scope>
      <managed-property>
        <property-name>id</property-name>
        <property-class>java.lang.Integer</property-class>
        <value>#{param.id}</value> 
      </managed-property>
     //etc
    

    使用隐藏字段保存id:

    <h:inputHidden value="#{editor.id}" />
    <h:commandLink action="#{editor.save}" value="save" />
    

    任何时候提交表单,都会发送这个值;如果验证失败,隐藏字段仍将使用 id 值呈现。如果验证成功,editor bean 将在调用 save 之前填充 id。

    【讨论】:

    • 其实我之前试过这个,但是验证失败的时候还是不存储id。可能我做错了什么,如果您能解释为什么“如果验证失败,隐藏字段仍将使用 id 值呈现”。从我的尝试来看,当验证失败时,GET 参数会被删除并丢失。
    • 查看 HTML 源代码以验证隐藏字段最初是否填充了 ID。任何时候提交页面,隐藏控件都会提交这个值。当验证失败时,可编辑的控件渲染器会写出最后提交的值,以便为下一次提交保留 id。 (其他任何情况,比如绑定到#{editor.id}outputText 将显示为空,因为验证失败时不会填充bean;验证阶段会阻止垃圾进入模型)。
    • 哦,是的,你是对的。你知道如何捕捉这些值吗?我的意思是以前/未验证的值?我也想在其他地方使用它们(我在左侧有一个可供编辑的项目列表)。这是在 JSF 中执行此操作的“正常”方式吗?我的意思是,如果有经验的 JSF 开发人员会这样做吗?或者是否有任何内置功能?非常感谢!
    • 如果您需要在渲染阶段提交值,您可以在commandLink 上使用param(例如&lt;f:param name="id" value="#{param.id}" /&gt;)。例如,这将使初始 URL 参数可用于 outputText。除此之外,(核心)JSF 并没有做任何使其与任何其他 HTTP 请求不同的“魔法”。
    • 明确一点:JSF 验证阻止垃圾进入模型;如果您需要以其他方式使用数据,请不要使用 JSF 验证;在操作中进行验证。我认为没有理由将其他形式的验证绑定到 JSF API,因此没有理由将它们构建到 JSF 生命周期中。
    【解决方案2】:

    Tomahawkt:saveState 完全符合您的要求。只需在您的页面中添加类似内容:

    <t:saveState value="#{bean.item.id}" />
    

    或者如果您想覆盖所有“未覆盖”的项目值:

    <t:saveState value="#{bean.item}" />
    

    如果您出于某些未知原因不想添加另一个组件库(我确实推荐 Tomahawk,它在标准 JSF 实现之上添加了更灵活的组件,例如t:dataList、@ 987654327@、t:selectOneRadio layout="spread"t:inputFileUpload 等),那么您也可以使用标准的&lt;h:inputHidden&gt; 组件在请求之间传递隐藏参数(它呈现&lt;input type="hidden"&gt;)。一个警告是,当验证阶段失败时,您仍然会丢失这些值。但这可以通过使用组件binding 而不是value 来解决。

    private HtmlInputHidden itemId = new HtmlInputHidden();
    private Item item = new Item();
    
    public void editItem() { // Action method when selecting an item for edit.        
        itemId.setValue(item.getId());
    }
    
    public void saveItem() { // Action method when saving edited item.
        item.setId((Integer) itemId.getValue());
    }
    

    和在JSF页面中有以下相同的形式:

    <h:inputHidden binding="#{bean.itemId}" />
    

    希望这会有所帮助。

    【讨论】:

    • 谢谢,这正是我想要的 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-02
    • 2021-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多