p:dataTable in a composite component

UI Components for JSF
Post Reply
Turjakas
Posts: 48
Joined: 22 Jan 2010, 17:07

05 Mar 2010, 11:01

Is it possible to use p:dataTable in a composite component?

I have the following code, which does not work correctly:

Code: Select all

 ...
        <p:dataTable id="itemTable"
            var="item" value="#{cc.attrs.value}"
            paginator="#{cc.attrs.value.size() > 8}" rows="8"
            selectionMode="single" selection="#{cc.attrs.selection}"
            update="itemTable" paginatorPosition="top">
  ...
It seems that the expression given to the value attribute of the composite component (#{cc.attrs.value}) is passed to the component implementation in some incompatible way. The same applies for #{cc.attrs.selection}.

With the code above I get an exception when trying to select a row in the table:

Code: Select all

javax.faces.model.NoRowAvailableException
	at javax.faces.model.ListDataModel.getRowData(ListDataModel.java:150)
	at javax.faces.component.UIData.getRowData(UIData.java:354)
	at org.primefaces.component.datatable.DataTableRenderer.decodeSingleSelection(DataTableRenderer.java:119)
	at org.primefaces.component.datatable.DataTableRenderer.decode(DataTableRenderer.java:58)
	at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:790)
	at javax.faces.component.UIData.processDecodes(UIData.java:980)
	at org.primefaces.component.datatable.DataTable.processDecodes(DataTable.java:348)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1042)
	at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:941)
	at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
	at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
	at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:79)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:277)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
	at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
	at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
	at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:332)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:233)
	at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
	at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
	at com.sun.grizzly.comet.CometEngine.executeServlet(CometEngine.java:473)
	at com.sun.grizzly.comet.CometEngine.handle(CometEngine.java:341)
	at com.sun.grizzly.comet.CometAsyncFilter.doFilter(CometAsyncFilter.java:84)
	at com.sun.grizzly.arp.DefaultAsyncExecutor.invokeFilters(DefaultAsyncExecutor.java:161)
	at com.sun.grizzly.arp.DefaultAsyncExecutor.interrupt(DefaultAsyncExecutor.java:137)
	at com.sun.grizzly.arp.AsyncProcessorTask.doTask(AsyncProcessorTask.java:88)
	at com.sun.grizzly.http.TaskBase.run(TaskBase.java:189)
	at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
	at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
	at java.lang.Thread.run(Thread.java:619)
The problem disappears if I replace #{cc.attrs.value} directly with the value passed to the composite component, but this is not what I want as I want to parameterize the "value" and "selection" parameters of p:dataTable.

cagatay.civici
Prime
Posts: 18616
Joined: 05 Jan 2009, 00:21
Location: Cybertron
Contact:

05 Mar 2010, 13:18

Well it should work, why not, maybe problem is how you define your composite component and the values.

Turjakas
Posts: 48
Joined: 22 Jan 2010, 17:07

05 Mar 2010, 13:46

I am passing an ArrayList to the value-attribute.

I don't know exactly how EL works in this case, but it seems like it just passes the return value of the given property to the composite component instead of providing a reference to the property. The return value is obviously not enough for p:dataTable to access the original getter and setter methods (which are needed in case of selection at least) for the property.

I guess EL supports different ways of passing parameters, such as pass-by-value or pass-by-reference (= the original EL expression).

Now, as I said, I'm not sure if this is the problem, could you try to reproduce it?

Turjakas
Posts: 48
Joined: 22 Jan 2010, 17:07

05 Mar 2010, 13:50

Oh, here is the composite component interface definition:

Code: Select all

  <composite:interface>
    <composite:attribute name="title" required="true" />
    <composite:attribute name="itemHeaderText" required="true" />
    <composite:attribute name="value" required="true" />
    <composite:attribute name="selection" required="true" />
    <composite:attribute name="update" required="true" />
  </composite:interface>
And I'm using it like this:

Code: Select all

<util:selectDialog title="Select campaign" itemHeaderText="Campaign name" value="#{activityBean.campaignList}" selection="#{activityBean.selectedCampaign}" update="activityList" />
The properties in activityBean have the following signatures:

Code: Select all

  private List<Campaign> campaignList;
  private Campaign selectedCampaign;

  public List<Campaign> getCampaignList() {
    return campaignList;
  }

  public Campaign getSelectedCampaign() {
    return selectedCampaign;
  }

  public void setSelectedCampaign(Campaign selectedCampaign) {
    this.selectedCampaign = selectedCampaign;
  }

User avatar
Oleg
Expert Member
Posts: 3805
Joined: 02 Oct 2009, 09:41
Location: Germany, Black Forest

05 Mar 2010, 15:18

This is a well know problem and I can help you :-)

You must extend you composite interface to "var" attribute and set it in the composite implementation with c:set into the datatable (set "var" by value expression is not allowed). Here is an example:

Code: Select all

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:c="http://java.sun.com/jsp/jstl/core"
  xmlns:composite="http://java.sun.com/jsf/composite">
<head><title>dataTable</title></head><body>
<composite:interface>
  <composite:attribute name="var"/>
  <composite:attribute name="value"/>
  <composite:facet name="header"/>
  <composite:facet name="footer"/>
</composite:interface>
<composite:implementation>
    <p:dataTable id="table" value="#{cc.attrs.value}">
    <c:set target="#{component}" property="var"
        value="#{cc.attrs.var}"/>
    <composite:insertFacet name="header"/>
    <composite:insertChildren/>
    <composite:insertFacet name="footer"/>
  </p:dataTable>
</composite:implementation>
</body></html>
Good luck!

Best regards.
Oleg.
PrimeFaces Cookbook (2. edition): http://ova2.github.io/primefaces-cookbook/ Learning Angular UI Development with PrimeNG: https://github.com/ova2/angular-develop ... th-primeng Blog: https://medium.com/@OlegVaraksin

Turjakas
Posts: 48
Joined: 22 Jan 2010, 17:07

05 Mar 2010, 16:02

Hi Oleg,

I do not completely understand how that solves the problem.

1. Can you provide an example how to use that kind of composite component? (e.g. how to specify columns, how do you refer to the "var" property)

2. What are the header and footer facets for in the example?

Turjakas
Posts: 48
Joined: 22 Jan 2010, 17:07

05 Mar 2010, 16:12

I quickly tested using c:set to set the var-attribute. I did the tests using two approaches: in first test I had the columns defined in the composite component (which is stupid as I define the var-attribute outside the component) and in the second one I used composite:insertChildren inside p:dataTable and I defined the columns as children to the composite component (= where I actually used the component). Both approaches populate the table correctly with items, but selecting a row still gives me the NoRowAvailableException.

Here's the code for the composite component: (second approach)

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:c="http://java.sun.com/jsp/jstl/core"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:composite="http://java.sun.com/jsf/composite"
      xmlns:p="http://primefaces.prime.com.tr/ui">

  <composite:interface>
    <composite:attribute name="uniqueId" required="true" />
    <composite:attribute name="title" required="true" />
    <composite:attribute name="itemHeaderText" required="true" />
    <composite:attribute name="value" required="true" />
    <composite:attribute name="var" required="true" />
    <composite:attribute name="selection" required="true" />
    <composite:attribute name="update" required="true" />
  </composite:interface>

  <composite:implementation>
    <h:outputLink value="javascript:void(0)" styleClass="iconAction"
                  onclick="#{cc.attrs.uniqueId}.show();">
      #{cc.attrs.title}
    </h:outputLink>

    <p:dialog header="#{cc.attrs.title}" width="300px"
              widgetVar="#{cc.attrs.uniqueId}" visible="false">
      <div>
        <p:commandButton value="Recently used" update="itemTable"
                         ajax="true" />
        <p:commandButton value="Recently created" update="itemTable"
                         ajax="true" />
      </div>
      <div>
        <h:outputText value="Search:" />
        <h:inputText />
      </div>
      <!-- references to cc.attrs do not work correctly here -->
      <p:dataTable id="itemTable"
          value="#{cc.attrs.value}"
          paginator="#{cc.attrs.value.size() > 8}" rows="8"
          selectionMode="single" selection="#{cc.attrs.selection}"
          update="itemTable" paginatorPosition="top">
        <c:set target="#{component}" property="var" value="#{cc.attrs.var}"/>
        <composite:insertChildren />
      </p:dataTable>
    </p:dialog>
  </composite:implementation>
</html>
And here is the code that uses it: (second approach)

Code: Select all

        <util:selectDialog uniqueId="selectCampaignDialog"
                           title="Select campaign..."
                           itemHeaderText="Campaign name"
                           value="#{activityBean.campaignList}"
                           var="item"
                           selection="#{activityBean.selectedCampaign}"
                           update="selectedCampaignText">
          <p:column>
            <f:facet name="header">
              <h:outputText value="Blah" />
            </f:facet>
            <h:outputText value="#{item.name}"/>
          </p:column>
        </util:selectDialog>
        <h:outputText id="selectedCampaignText" value="#{activityBean.selectedCampaign.name}" />

User avatar
Oleg
Expert Member
Posts: 3805
Joined: 02 Oct 2009, 09:41
Location: Germany, Black Forest

05 Mar 2010, 16:17

Turjakas wrote:Hi Oleg,

I do not completely understand how that solves the problem.

1. Can you provide an example how to use that kind of composite component? (e.g. how to specify columns, how do you refer to the "var" property)

2. What are the header and footer facets for in the example?
Hi Turjakas,

You use this composite component as quite normally datatable. For example

Code: Select all

<!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:md="http://java.sun.com/jsf/composite/mydatatable">
<head>
    <title>Customer List</title>
</head>
<body>
    <ui:composition template="/META-INF/templates/customerTemplate.xhtml">
            <h:form id="form">
                <md:dataTable id="customers" var="customer" value="#{customerListBean.customerList}">
                    <h:column>
                        <f:facet name="header">
                            <h:outputText value="#{msgs.name}"/>
                        </f:facet>
                        <h:commandLink value="#{customer.fullName}" action="#{customerBean.showCustomer(customer.id)}"/>
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            <h:outputText value="#{msgs.email}"/>
                        </f:facet>
                        <h:outputText value="#{customer.email}"/>
                    </h:column>
                    <h:column>
                        <h:commandLink value="#{msgs.delete}" action="#{customerListBean.deleteCustomer(customer)}">
                            <f:ajax render="@form"/>
                        </h:commandLink>
                    </h:column>
                </mc:dataTable>
            </h:form>
    </ui:composition>
</body>
</html>
PrimeFaces Cookbook (2. edition): http://ova2.github.io/primefaces-cookbook/ Learning Angular UI Development with PrimeNG: https://github.com/ova2/angular-develop ... th-primeng Blog: https://medium.com/@OlegVaraksin

Turjakas
Posts: 48
Joined: 22 Jan 2010, 17:07

05 Mar 2010, 16:38

Ok. Then I got the idea behind your example right.

However, I still have the problem with row selection.

Can you try using instant row selection using AJAX in your dataTable using the following attributes ?

<p:dataTable ..... selection="#{bean.selectedItem}" update="selectedItemText" selectionMode="single" .... />

(you need the update-attribute and a respective component displaying the results for this to work)

Does row selection work for you then?

helloprimefaces
Posts: 56
Joined: 28 Sep 2009, 17:44

05 Mar 2010, 18:56

Hi,
p:dataTable row selection is not working stable and moreover there is no possibility to rerender/update the whole datatable with ajax row selection (or thru a h:checkbox component).
If you're interested, then vote for this issue
http://code.google.com/p/primefaces/iss ... ail?id=506
and
http://code.google.com/p/primefaces/iss ... ail?id=508

Hope Primefaces team will fix these issues in near future.

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 41 guests