如何在发布后使​​用链接创建JSF表

时间:2012-03-19 10:34:04

标签: jsf-2 myfaces

我想显示一个表单,最终用户可以在其中输入详细信息,并且帖子将生成包含基于用户输入的筛选列表的表。此表应包含每行的链接以选择该特定行并返回详细视图。

帐户-list.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
xmlns:utils="http://java.sun.com/jsf/composite/snippets" template="/WEB-INF/templates/default.xhtml">

    <ui:define name="title"></ui:define>
    <ui:define name="content">
        <h:form id="search">
            <fieldset>
                <legend>Search for account</legend>
                <div class="account_list_section">
                    <span class="account_section_title"><h:outputLabel for="id" value="Account ID" /></span>
                    <span class="account_list_item">
                        <h:inputText id="id" value="#{accountsCrudBean.searchId}" styleClass="field_inputtext_account" />
                    </span>
                </div>
                <div class="account_list_section">
                    <span class="account_section_title"><h:outputLabel for="name" value="Account Name" /></span>
                    <span class="account_list_item">
                        <h:inputText id="name" value="#{accountsCrudBean.searchName}" styleClass="field_inputtext_account" />
                    </span>
                </div>
                <h:commandButton id="search" value="Display" action="#{accountsCrudBean.actionSearch}" />
            </fieldset>
        </h:form>

        <h:form id="view" rendered="#{accountsCrudBean.dataItemId.value != null}">
            <h:dataTable var="dataItem" binding="#{accountsCrudBean.dataTable}" value="#{accountsCrudBean.list}" id="accountListTable"
                columnClasses="accountsCrudBeanTable_row_date, transactionsListTable_row_amount, transactionsListTable_row_balance, transactionsListTable_row_description" styleClass="transactionsListTable">
                <h:column headerClass="transactionsListTable_header_amount">
                    <f:facet name="header">Id</f:facet>
                    <h:commandLink value="#{dataItem.id}" action="#{accountsCrudBean.editDataItem}" />
                </h:column>
                <h:column headerClass="transactionsListTable_header_balance">
                    <f:facet name="header">Name</f:facet>#{dataItem.name}</h:column>
                <h:column headerClass="transactionsListTable_header_description">
                    <f:facet name="header">Total Balance</f:facet>#{dataItem.totalBalance}</h:column>
            </h:dataTable>
            <h:inputHidden binding="#{accountsCrudBean.dataItemId}" />
        </h:form>
    </ui:define>
</ui:composition>

帐户-edit.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:utils="http://java.sun.com/jsf/composite/snippets"
    template="/WEB-INF/templates/default.xhtml">

    <ui:define name="title"></ui:define>
    <ui:define name="content">
        <h:form id="edit" rendered="#{accountsCrudBean.dataItemId.value != null}">
            <fieldset>
                <legend>View account 1</legend>
                <div class="account_list_section">
                    <span class="account_section_title"><h:outputLabel for="id" value="Account ID" /></span>
                    <span class="account_list_item">
                        #{accountsCrudBean.dataItemId.value}
                    </span>
                </div>
                <div class="account_list_section">
                    <span class="account_section_title"><h:outputLabel for="name" value="Account Name" /></span>
                    <span class="account_list_item">
                        <h:inputText readonly="true" id="name" value="#{accountsCrudBean.dataItem.name}" styleClass="field_inputtext_account" />
                    </span>
                </div>

                <div class="account_list_section">
                    <span class="account_section_title"><h:outputLabel for="accountOwners" value="Owners" /></span>
                    <span class="account_list_item">
                        <h:selectOneListbox readonly="true" id="accountOwners" value="#{accountsCrudBean.selectedOwner}">
                            <f:selectItems value="#{accountsCrudBean.accountOwners}" />
                        </h:selectOneListbox>       
                    </span>
                </div>      

                <h:inputHidden binding="#{accountsCrudBean.dataItemId}" />

                <h:commandButton id="edit" value="Save" action="#{accountsCrudBean.actionSearch}" />
            </fieldset>
        </h:form>
        <h:outputText value="No item selected." rendered="#{accountsCrudBean.dataItemId.value == null}" />
    </ui:define>
</ui:composition>

AccountsCrudBean.java:

@ManagedBean
@SessionScoped
public class AccountsCrudBean extends JsfManagedBeanBase {

    private static final long serialVersionUID = 1L;

    @EJB
    AccountsManagerLocal accountsManager;

    private Long searchId;
    private String searchName;

    private String selectedOwner;

    private Account dataItem;
    private HtmlDataTable dataTable;
    private HtmlInputHidden dataItemId = new HtmlInputHidden();

    private List<Account> accountList = null;

    public AccountsCrudBean() {
    }

    public Long getSearchId() {
        return searchId;
    }

    public void setSearchId(Long searchId) {
        this.searchId = searchId;
    }

    public String getSearchName() {
        return searchName;
    }

    public void setSearchName(String searchName) {
        this.searchName = searchName;
    }

    public HtmlInputHidden getDataItemId() {
        return dataItemId;
    }

    public Account getDataItem() {
        return dataItem;
    }

    public void setDataItem(Account dataItem) {
        this.dataItem = dataItem;
    }

    public HtmlDataTable getDataTable() {
        return dataTable;
    }

    public void setDataTable(HtmlDataTable dataTable) {
        this.dataTable = dataTable;
    }

    public void setDataItemId(HtmlInputHidden dataItemId) {
        this.dataItemId = dataItemId;
    }

    public String getSelectedOwner() {
        return selectedOwner;
    }

    public void setSelectedOwner(String selectedOwner) {
        this.selectedOwner = selectedOwner;
    }

    public List<Account> getList() {
        if (accountList == null) {
            actionLoad();
        }
        return accountList;
    }

    private void actionLoad() {
        if (searchId != null) {
            Account account = accountsManager.getAccount(searchId);
            accountList = Arrays.asList(account);
        } else if (searchName != null) {
            accountList = accountsManager.findAccountByName(searchName);
        } else if (dataItemId != null && dataItemId.getValue() != null) {
            Account account = accountsManager.getAccount(Long
                    .valueOf(dataItemId.getValue().toString()));
            accountList = Arrays.asList(account);
        } else
            accountList = new ArrayList<Account>();
    };

    public void actionSearch() {
        dataItem = (Account) dataTable.getRowData();
        dataItemId.setValue(dataItem.getId());
        actionLoad();
    }

    public Map<String, User> getAccountOwners() {
        List<User> owners = accountsManager.getUsers(dataItem);
        LinkedHashMap<String, User> map = new LinkedHashMap<String, User>();
        for (User user : owners) {
            map.put(user.getFirstName() + " " + user.getLastName(), user);
        }
        return map;
    }

    public String editDataItem() {
        dataItem = (Account) dataTable.getRowData();
        dataItemId.setValue(dataItem.getId());
        return "accounts-edit";
    }
}

这适用于JBoss 7.1但是在6上它失败了:

javax.faces.el.EvaluationException: javax.el.ELException: /s/accounts-list.xhtml at line 22 and column 94 action="#{accountsCrudBean.actionSearch}": java.lang.IllegalArgumentException: row is unavailable
    at javax.faces.component._MethodExpressionToMethodBinding.invoke(_MethodExpressionToMethodBinding.java:96)
    at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:100)
    at javax.faces.component.UICommand.broadcast(UICommand.java:120)
    at javax.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:889)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:238)
    at javax.faces.component.UIViewRoot._process(UIViewRoot.java:1201)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:627)
    at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:34)
    at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:171)
    at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:324)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242)
    at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:67)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:274)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242)
    at com.demo.server.ejb.security.AuthenticationFilter.doFilter(AuthenticationFilter.java:35)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:274)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
    at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:181)
    at org.jboss.modcluster.catalina.CatalinaContext$RequestListenerValve.event(CatalinaContext.java:285)
    at org.jboss.modcluster.catalina.CatalinaContext$RequestListenerValve.invoke(CatalinaContext.java:261)
    at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:88)
    at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:100)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:159)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.jboss.web.tomcat.service.request.ActiveRequestResponseCacheValve.invoke(ActiveRequestResponseCacheValve.java:53)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:654)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:951)
    at java.lang.Thread.run(Thread.java:722)
Caused by: javax.el.ELException: /s/accounts-list.xhtml at line 22 and column 94 action="#{accountsCrudBean.actionSearch}": java.lang.IllegalArgumentException: row is unavailable
    at org.apache.myfaces.view.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:95)
    at javax.faces.component._MethodExpressionToMethodBinding.invoke(_MethodExpressionToMethodBinding.java:88)
    ... 35 more
Caused by: java.lang.IllegalArgumentException: row is unavailable
    at javax.faces.model.ListDataModel.getRowData(ListDataModel.java:69)
    at javax.faces.component.UIData.getRowData(UIData.java:462)
    at com.demo.server.web.AccountsCrudBean.actionSearch(AccountsCrudBean.java:130)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:196)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
    at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:43)
    at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:56)
    at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:43)
    at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:56)
    at org.apache.myfaces.view.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:83)
    ... 36 more

这基于http://balusc.blogspot.com/2006/06/using-datatables.html#AddBackingBeanActionToEveryRow

在帖子上,作者使用@RequestScoped bean但是如果我尝试将bean更改为@RequestScoped,则过滤器不起作用,并且我没有得到带有链接的表。

感谢。

1 个答案:

答案 0 :(得分:0)

您的bean在会话范围内。你根本不需要<h:inputHidden binding="...">。删除它和所有相关代码。您的支持bean操作方法应如下所示:

public void actionSearch() {
    actionLoad();
}

public String editDataItem() {
    dataItem = (Account) dataTable.getRowData();
    return "accounts-edit";
}

另请在#{accountsCrudBean.dataItemId}中替换视图中的#{accountsCrudBean.dataItem.id}


对具体问题

无关,请注意该文章已有近6年历史,基于JSF 1.x.目前,使用JSF 2.x和EL 2.2,还有其他更简单的方法来获取所选行。我最喜欢的是

<h:commandLink value="#{dataItem.id}" action="#{accountsCrudBean.editDataItem(dataItem)}" />

public String editDataItem(Account dataItem) {
    this.dataItem = dataItem;
    return "accounts-edit";
}