JSF 2:h:link 和 getrowdata

发布于 2024-10-31 07:53:48 字数 2903 浏览 1 评论 0原文

如果我在 books.xhtml 中有一个 h:dataTable 提供记录列表,并且我想查看特定记录,然后添加或编辑该记录,目前我有这个:

<h:dataTable #{BookBean.books}" var="books">
   <h:link outcome="bookview" value="#{books[1]}">
      <f:param name="id" value="#{books[2]}" />
   </h:link>
</h:dataTable>

我发现我需要包含 才能显示单击链接的 CSS 状态;否则,如果我没有 ,每次我单击上面代码中 h:link 标记呈现的链接时,所有链接都会更改为 CSS 单击状态。

另外,我在某处读到过有关 getrowdata() 的内容,但我无法让它工作。这是使用 更好的替代方案吗?

我在 BookBean 类中尝试了 getrowdata() 方法,如下所示:

private DataModel<BookModel> books;
private BookModel currentBook;

public String view()
{
     currentBook = books.getRowData();
     return "bookview";
}

在 bookview.xhtml 中我有这个:

<h:dataTable value="#{BookBean.view}" var="item">
    ... // render content here
<h:dataTable>

但我收到有关未找到属性的错误。很抱歉问这个问题,但我仍然不明白 JSF 2 的一些强大功能。请问有了解 h:linkgetrowdata 用法的专家吗?用外行术语或一些基本代码示例向我解释。谢谢。

更新: 根据下面的 @BalusC 建议更改了类。 BookModel 类是:

@Entity
public class BookModel implements Serializable
{
   private Long id;
   private String title;
   private String author;   

   // getters and setters here
 }

BookService 类如下所示:

@Stateless
public class BookService
{
    @PersistenceContext(unitName = "persistentUnit")
    protected EntityManager entityManager;

    public BookModel create() {
       return new BookModel();
    }

    public void delete(BookModel bookModel) {
       bookModel = entityManager.merge(bookModel);
       entityManager.remove(bookModel);
    }

    public BookModel update(BookModel bookModel) {
       return entityManager.merge(bookModel);
    }

    public BookModel find(Long id) {
       return entityManager.find(BookModel.class, id);
    }
}

BookBean 类是:

@ManagedBean(name = "bookBean")
@RequestScoped
public class BookBean implements Serializable
{
    @EJB
    private BookService bookService;

    @ManagedProperty(value = "#{param.id}")
    private Long id;

    private DataModel<BookModel> books;
    private BookModel currentBook;

    @PostConstruct
    public void init() {
        currentBook = bookService.find(id);
    }

    public BookModel getCurrentBook() {
       return currentBook;
    }

    public void setCurrentBook(BookModel currentBook) {
       this.currentBook = currentBook;
    }
 }

运行上面的 BookBean 类导致了此错误:java .lang.IllegalStateException:WEB9031:WebappClassLoader无法加载资源[org.apache.openjpa.util.LongId],因为它尚未启动,或已停止。这就是我现在被困住的地方。

仅供参考:我的开发环境是 Glassfish 3.1、Apache OpenJPA 2.1 和 JSF 2.1.0(与 Glassfish 捆绑在一起)

If I have a h:dataTable in books.xhtml providing a list of records and I want to view a particular record, then add or edit that record, currently I have this:

<h:dataTable #{BookBean.books}" var="books">
   <h:link outcome="bookview" value="#{books[1]}">
      <f:param name="id" value="#{books[2]}" />
   </h:link>
</h:dataTable>

I found out that I need to include <f:param> in order to show the CSS status of clicked link; otherwise if I don't have <f:param>, every time I clicked on a link rendered by h:link tags in the codes above, all links are changed to CSS clicked status.

Also, I read somewhere about the getrowdata() but I haven't been able to get it work. Is this a better alternative to using <f:param>?

I have tried the getrowdata() method in my BookBean class as followed:

private DataModel<BookModel> books;
private BookModel currentBook;

public String view()
{
     currentBook = books.getRowData();
     return "bookview";
}

and in bookview.xhtml I have this:

<h:dataTable value="#{BookBean.view}" var="item">
    ... // render content here
<h:dataTable>

but I get an error about the property not found. Sorry for asking this question but I still don't understand yet some of the powerful features of JSF 2. Can some expert who understand the usage of h:link and getrowdata please explain to me in layman terms or perhaps with some basic code example. Thank you.

UPDATE:
Changed classes based on @BalusC suggestions below. BookModel class is:

@Entity
public class BookModel implements Serializable
{
   private Long id;
   private String title;
   private String author;   

   // getters and setters here
 }

The BookService class looks like this:

@Stateless
public class BookService
{
    @PersistenceContext(unitName = "persistentUnit")
    protected EntityManager entityManager;

    public BookModel create() {
       return new BookModel();
    }

    public void delete(BookModel bookModel) {
       bookModel = entityManager.merge(bookModel);
       entityManager.remove(bookModel);
    }

    public BookModel update(BookModel bookModel) {
       return entityManager.merge(bookModel);
    }

    public BookModel find(Long id) {
       return entityManager.find(BookModel.class, id);
    }
}

The BookBean class is:

@ManagedBean(name = "bookBean")
@RequestScoped
public class BookBean implements Serializable
{
    @EJB
    private BookService bookService;

    @ManagedProperty(value = "#{param.id}")
    private Long id;

    private DataModel<BookModel> books;
    private BookModel currentBook;

    @PostConstruct
    public void init() {
        currentBook = bookService.find(id);
    }

    public BookModel getCurrentBook() {
       return currentBook;
    }

    public void setCurrentBook(BookModel currentBook) {
       this.currentBook = currentBook;
    }
 }

Running the BookBean class above caused this error: java.lang.IllegalStateException: WEB9031: WebappClassLoader unable to load resource [org.apache.openjpa.util.LongId], because it has not yet been started, or was already stopped. This is where I'm stuck at the moment.

FYI: My dev environment is Glassfish 3.1, Apache OpenJPA 2.1 and JSF 2.1.0 (that comes bundled with Glassfish)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

南汐寒笙箫 2024-11-07 07:53:48

代码中有两个缺陷:

  • h:link 触发 GET 请求,而不是 POST 请求。 DataModel#getRowData() 在这里也没有什么用处,因为您无法将 bean 操作附加到触发 GET 请求的组件。

  • 带有 public String view() 没有任何意义。数据表的值必须是项目的集合,而不是 bean 操作方法。


我知道您希望表中的每个图书项目都有一个 GET 链接,该链接指向有关该图书项目的一些详细信息页面。修复详细信息页面如下:

bookview.xhtml

<h:outputText value="#{bookBean.currentBook.id}" />
<h:outputText value="#{bookBean.currentBook.author}" />
<h:outputText value="#{bookBean.currentBook.title}" />
...

BookBean 如下:

@ManagedBean
@RequestScoped
public BookBean {

    @ManagedProperty(value="#{param.id}")
    private Long id;

    private BookModel currentBook;

    @PostConstruct 
    public void init() {
        currentBook = bookDAO.find(id);
    }

    // ...
}

@ManagedProperty 将设置 GET 请求参数。 @PostConstruct 将根据参数预加载正确的书籍。

请注意,这与 POST-Redirect-GET 模式无关。

There are two flaws in the code:

  • The h:link fires a GET request, not a POST request. The DataModel#getRowData() is not useful here either since you cannot attach bean actions to components which fire a GET request.

  • The <h:dataTable value="#{BookBean.view}"> with public String view() makes no sense. The datatable's value has got to be a collection of items, not a bean action method.


I understand that you want a GET link on every book item in the table which points to some detail page about the book item. Fix the detail page as follows:

bookview.xhtml

<h:outputText value="#{bookBean.currentBook.id}" />
<h:outputText value="#{bookBean.currentBook.author}" />
<h:outputText value="#{bookBean.currentBook.title}" />
...

And the BookBean as follows:

@ManagedBean
@RequestScoped
public BookBean {

    @ManagedProperty(value="#{param.id}")
    private Long id;

    private BookModel currentBook;

    @PostConstruct 
    public void init() {
        currentBook = bookDAO.find(id);
    }

    // ...
}

The @ManagedProperty will set the GET request parameter. The @PostConstruct will preload the right book based on the parameter.

Please note that this has nothing to do with POST-Redirect-GET pattern.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文