I want to put a filter of a p:datatable into a composite component. The filter use the p:inputText tag and an p:ajax tag to define a typing delay. The problem is, that the converter inside the composite component do nothing. When I use javax.faces.Long, the filter is always String.
The working code, that I want to use in a facelet:
<p:column headerText="colum title"
filterBy="#{p.p.idx}" sortBy="#{p.p.idx}">
<f:facet name="filter">
<p:inputText id="indexFilterInput"
converter="javax.faces.Long" class="ui-column-filter">
<p:ajax event="keyup" delay="800"
oncomplete="PF('portDT').filter()" />
</p:inputText>
</f:facet>
<h:outputText value="#{portRow.portIdx}" />
</p:column>
I put the f:facet into the composite component:
<ui:component xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:cc="http://xmlns.jcp.org/jsf/composite">
<cc:interface>
<cc:attribute name="widgetVar" />
<cc:attribute name="delay" />
<cc:attribute name="converter" />
<cc:insertFacet name="filter" />
</cc:interface>
<cc:implementation>
<f:facet name="filter">
<p:inputText id="filterInput" converter="#{cc.attrs.converter}"
class="ui-column-filter" type="search">
<p:ajax event="keyup" delay="#{cc.attrs.delay}"
oncomplete="PF('#{cc.attrs.widgetVar}').filter()" />
</p:inputText>
</f:facet>
</cc:implementation>
</ui:component>
Here is the call of the component gf:filterField:
<p:column style="width:4em"
headerText="#{lbl['general.column.id']}" exportable="true"
filterBy="#{p.p.id}" sortBy="#{p.p.id}">
<gf:filterField id="index" widgetVar="portDT" delay="800" converter="javax.faces.Long"/>
<h:outputText value="#{portRow.portId}" />
</p:column>
When change the converter in the p:inputText inside the composite component, the converter is also ignored. I need to pass the converter as a parameter, because some columns are String columns and some are Long.
Is there any other tag in the cc:interface as cc:attribute?
Related
This question already has answers here:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
(6 answers)
Closed 7 years ago.
What I would like to do is to update orderList in every time when checkbox has been (un-)checked.
My component is unaccessible with faces error. The component is inside form with id="form"
14:33:29,614 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (default task-9) Error Rendering View[/pages/view.xhtml]: javax.faces.FacesException: Cannot find component with expression ":form:orderList" referenced from "form:j_idt34:j_idt88:j_idt96:0:j_idt100".
I have tried several solutions including: :form, form, :orderList, orderList, form:panelGridChoice:orderList, :panelGridChoice:orderList, :form:panelGridChoice:orderList, :form:orderList
This is my view
<composite:implementation>
<h:outputStylesheet library="css" name="form.css" />
<h:outputScript>
replaceMedia();
</h:outputScript>
<ui:decorate template="answerDecorator.xhtml">
<ui:define name="additionalForms">
<h:outputText value="#{cc.attrs.question.additionalExplanation}" styleClass="text-normal" escape="false" />
</ui:define>
<ui:define name="component">
<p:panelGrid id="panelGridChoice" columns="1" cellpadding="0" styleClass="inline" columnClasses="" >
<p:dataTable var="answer" value="#{cc.attrs.question.possibleAnswers}">
<p:column headerText="#{msg['survey.question.chooseAnswerList']}" styleClass="thirty-percent">
<h:outputText value="#{answer.text}" />
</p:column>
<p:column headerText="#{msg['survey.question.chooseAnswer']}" styleClass="ten2-percent" >
<p:selectBooleanCheckbox value="#{answer.checked}" >
<p:ajax event="change" process="#this" update=":form:orderList" listener="#{cc.attrs.question.setCheckedAnswers}" />
</p:selectBooleanCheckbox>
</p:column>
</p:dataTable>
<p:orderList id="orderList" value="#{cc.attrs.question.checkedAnswers2Order}" var="answer" itemLabel="#{answer.text}"
converter="entityConverter" itemValue="#{answer}" controlsLocation="left" >
<f:facet name="caption">#{msg['survey.default.makeOrder']}</f:facet>
</p:orderList>
</p:panelGrid>
</ui:define>
</ui:decorate>
</composite:implementation>
Where answerDecorator.xhtml is defined as
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:panelGrid columns="1" style="margin-bottom:10px" cellpadding="5" styleClass="borderless survey-panel-max">
<h:outputText value="#{cc.attrs.question.questionText}" styleClass="text-header"/>
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5" styleClass="borderless top-alignment">
<ui:insert name="additionalForms" />
</h:panelGrid>
</h:panelGrid>
<ui:insert name="component" />
This can be really annoying, so in situations like this I usually target the components by style class. Try adding styleClass="orderList" to <p:orderList>, and target it with #(.orderList).
Well.
I created a custom component to CRUD and the form page is a parameter.
In this case I need two pages, one to define the component and another with the form.
Is there any way to do that?
As follow:
Implementation:
Component
<cc:interface>
<cc:attribute name="formPage" type="java.lang.String" required="true"/>
.....
</cc:interface>
<cc:implementation>
...
<h:form id="form-crud">
<ui:include src="#{cc.attrs.formPage}" />
</h:form>
...
</cc:implementation>
Page 1: crud.xhtml
<ui:define name="content-template" >
<comp:crud
paginaForm="crud-form.xhtml" />
</ui:define>
Page 2: crud-form.xhtml
<html ...
<p:panelGrid id="grid-crud" columns="2" >
<h:outputLabel for="dsName" value="Name: " />
<p:inputText id="dsName" value="#{crudBean.dsName}"/>
</p:panelGrid>
</html>
New Implementation (sample)
To simplify, I would like to have component defnition and form in the same page, something like that. Is it possible?
I know I could use a template, but the custom componet has more attributes.
New Component
<cc:implementation>
...
<h:form id="form-crud">
<XX:SOMETING name="#{cc.attrs.formContent}" />
</h:form>
...
</cc:implementation>
New Page 1: new-crud.xhtml
...
<ui:define name="content-template" >
<comp:crud
form="new-form" />
<XX:SOMETING id="new-form">
<p:panelGrid id="grid-crud" columns="2" >
<h:outputLabel for="dsName" value="Name: " />
<p:inputText id="dsName" value="#{crudBean.dsName}"/>
</p:panelGrid>
</XX:SOMETING>
</ui:define>
...
You can make use of <f:facet> exactly like as those work with e.g. <h:dataTable>/<h:column> header/footer.
First declare a <cc:facet> with the desired name:
<cc:interface>
<cc:facet name="form" />
</cc:interface>
Then declare a <cc:renderFacet> in the desired place where it should end up:
<cc:implementation>
...
<h:form>
<cc:renderFacet name="form" />
</h:form>
...
</cc:implementation>
Now you can use it as follows:
<comp:crud>
<f:facet name="form">
...
</f:facet>
</comp:crud>
Please note that this construct is also possible with "plain vanilla" Facelets tagfiles via <ui:define>/<ui:insert> mechanisms.
I'm attempting to use a t:radio in my rich:datatable but it's always complaining about the fact that it can't find the component. I did some googling and I have to declare the full name, but I actually think I'm doing that.
Anyone can point me what I'm doing wrong? The code (I'm not going to give a minified version because I'm guessing it's going wrong with the compositions):
letterDetailTemplate.xhtml:
<h:form id="generateLetterForm">
<ui:include src="addStandardLetterMain.xhtml" />
<ui:include src="addStandardLetterText.xhtml" />
<ui:include src="buttons.xhtml" />
</h:form>
addStandardLetterText.xhtml (the radio button is over here, in the slrDataTable):
<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:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:e="http://minfin.regondes2/entity"
xmlns:ccffdecorate="http://java.sun.com/jsf/composite/ccffdecorate"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:l="http://minfin.regondes2/layout"
xmlns:o="http://omnifaces.org/ui"
xmlns:t="http://myfaces.apache.org/tomahawk">
<ui:param name="entityBB" value="#{letterBB}" />
<ui:param name="type" value="Dossier.Letter" />
<l:screenzone id="addStandardLetterTextPanel"
title="#{AppMessages[type.concat('.addStandardLetterText.title')]}">
<h:outputStylesheet name="letterText.css" library="stylesheets" />
<h:outputScript name="letter.js" library="scripts" />
<a4j:region>
<a4j:outputPanel id="letterTextPanel">
<h:inputTextarea id="letterText" name="letterText"
value="#{entityBB.entity.text}" styleClass="letterText" />
<script type="text/javascript">
language: '#{screen.locale.language}'
CKEDITOR.replace( 'generateLetterForm:letterTex', {
});
</script>
</a4j:outputPanel>
<h:panelGroup styleClass="rButtonPanelAlignLeft" layout="block"
rendered="#{dossierContextBB.dossierContext == 'EDIT'}">
<a4j:commandButton
value="#{AppMessages[type.concat('.add.region')]}"
actionListener="#{entityBB.findAvailableRegionStandardLetters()}"
render="slrPopupFormPanel" limitRender="true" status="ajaxStatus"
onclick="LETTER.CKUpdate()"
oncomplete="#{rich:component('addStandardLetterRegion')}.show();" />
</h:panelGroup>
</a4j:region>
<rich:popupPanel id="addStandardLetterRegion" modal="true"
onmaskclick="#{rich:component('addStandardLetterRegion')}.hide()"
autosized="true">
<f:facet name="header">
<h:outputText
value="#{AppMessages['Dossier.Letter.StandardLetter.region.popup.title']}" />
</f:facet>
<f:facet name="controls">
<h:outputLink value="#"
onclick="#{rich:component('addStandardLetterCentrum')}.hide(); return false;">
X
</h:outputLink>
</f:facet>
<a4j:outputPanel id="slrPopupFormPanel">
<t:selectOneRadio id="slrOption"
value="#{standardLetterBB.selected}" layout="spread"
converter="#{standardLetterBB.converter}">
<f:selectItems value="#{entityBB.availableStandardLetterText}"
var="standardLetter" itemLabel="" itemValue="#{standardLetter}" />
</t:selectOneRadio>
<rich:dataTable id="slrDataTable"
value="#{entityBB.availableStandardLetterText}"
var="standardLetter" noDataLabel="No standard letters found"
rowKeyVar="index">
<rich:column headerClass="ListTitle">
<t:radio for="generateLetterForm:slrDataTable:slrOption" index="#{index}" />
</rich:column>
<e:column entity="#{standardLetter.dossierType}" type="#{type}"
property="type" />
<e:column entity="#{standardLetter}" type="#{type}"
property="numbering" />
<e:columnTranslatable entity="#{standardLetter}" type="#{type}"
property="text" />
</rich:dataTable>
</a4j:outputPanel>
<div class="rButtonPanel">
<h:commandButton value="#{AppMessages['general.action.add']}">
<a4j:ajax event="click" execute="generateLetterForm"
listener="#{entityBB.addMotivationToReport}"
oncomplete="#{rich:component('addStandardLetterRegion')}.hide()"
render="reportMotivationTextPanel" limitRender="true" />
</h:commandButton>
<a4j:commandButton value="#{AppMessages['general.action.cancel']}"
onclick="#{rich:component('addStandardLetterRegion')}.hide()"
limitRender="true" immediate="true" bypassUpdates="true" />
</div>
</rich:popupPanel>
</l:screenzone>
Note that this view works and renders and displays the data from the backingbean when I remove the t:radio.
The errormessage I'm getting is:
SEVERE: java.lang.IllegalStateException: Could not find component 'generateLetterForm:slrDataTable:slrOption' (calling findComponent on component 'generateLetterForm:slrDataTable:0:j_idt258')
javax.faces.FacesException: java.lang.IllegalStateException: Could not find component 'generateLetterForm:slrDataTable:slrOption' (calling findComponent on component 'generateLetterForm:slrDataTable:0:j_idt258')
Change for="generateLetterForm:slrDataTable:slrOption" to for=":generateLetterForm:slrOption" and specify id for your t:radio in datatable also. Don't forget the ":" before generateLetterForm.
I have implemented a composite component in JSF using primefaces.
<ui:component ...>
<cc:interface>
<cc:facet name="header"/> ...
<cc:interface>
<cc:implementation>
<p:dataTable>
<f:facet name="header">
<c:choose>
<c:when test="#{empty cc.attrs.metadata.headerText}">
<cc:insertFacet name="header" required="true"/>
</c:when>
<c:otherwise>
#{cc.attrs.headerText}
</c:otherwise>
</c:choose>
</f:facet> ...
</dataTable>
</cc:implementation>
When I use it in a normal page it works fine as expected rendering the datatable.
<ui:composition>
<nav:dataTable/>
<f:facet name="header">
<h:outputText value="headerText" />
</f:facet>
</ui:composition>
But when I use it inside a dialog which uses the above composite component, it throws
component.xhtml #28,54
Unable to find facet named 'header' in parent
composite component with id 'j_idt129'
I am making a ajax call to invoke this dialog on click of a link. The dialog comes in different shape and throwing this error in console. Has anyone faced it ? Any help is really appreciable.
cc:insertFacet inserts the whole f:facet tag, so you shouldn't wrap it into another f:facet tag within the composite implementation. As you are writing a custom p:dataTable I think it's easier to overwrite the already existing header facelet as an interface declaration and conditionally render it using JSTL utilities:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:body>
<composite:interface>
<composite:facet name="header" />
<composite:attribute name="title" />
</composite:interface>
<composite:implementation>
<p:dataTable>
<!-- If the facet is given at parent, insert it.
Otherwise, provide the title given by the attribute -->
<c:choose>
<c:when test="#{not empty cc.facets.header}">
<composite:insertFacet name="header" />
</c:when>
<c:otherwise>
<f:facet name="header">
#{cc.attrs.title}
</f:facet>
</c:otherwise>
</c:choose>
<p:column headerText="column" />
</p:dataTable>
</composite:implementation>
</h:body>
</html>
Using it as:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:comp="http://java.sun.com/jsf/composite/comp">
<f:view>
<h:head />
<h:body>
<h:form>
<comp:myTable title="header">
<f:facet name="header">
<h:outputText value="text" />
</f:facet>
</comp:myTable>
<comp:myTable title="Custom header" />
<p:commandButton type="button" onclick="dialog.show()"
value="show in dialog" />
<p:dialog widgetVar="dialog">
<comp:myTable title="header">
<f:facet name="header">
<h:outputText value="text" />
</f:facet>
</comp:myTable>
</p:dialog>
</h:form>
</h:body>
</f:view>
</html>
When I defined 2 actionListeners in a composite table, the first actionListener will be called twice when I click it, but the second listener works fine without the problem. Even I switched the 2 listeners, always the first one called twice and the second one fine.
Here is the xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:asias="http://java.sun.com/jsf/composite/components/asias"
xmlns:test="http://java.sun.com/jsf/composite/test">
<h:head />
<h:body>
<h:form id="communityMembersForm">
<test:outertable list="#{memberController.members}"
title="Nested Table Test">
<f:actionListener for="sortAction"
binding="#{memberController.sortActionListener}" />
<f:actionListener for="actions"
binding="#{memberController.actionsActionListener}" />
</test:outertable>
</h:form>
</h:body>
</html>
MemberController is a viewScoped managed bean. outertable is defined as:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:test="http://java.sun.com/jsf/composite/test"
xmlns:asias="http://java.sun.com/jsf/composite/components/asias">
<composite:interface>
<composite:attribute name="list" required="true" />
<composite:attribute name="title" required="true" />
<composite:actionSource name="sortAction" targets="communityMembersPage" />
<composite:actionSource name="actions" targets="communityMembersPage" />
</composite:interface>
<composite:implementation>
<div>
<h3>#{cc.attrs.title}</h3>
<asias:memberTable id="communityMembersPage" memberList="#{cc.attrs.list}"
showPhone="true" showRoles="true" showAffiliation="true"
showLastLoginDate="true" showActions="true" allowSortLastName="true"
allowSortFirstName="true" allowSortEmail="true" />
</div>
</composite:implementation>
</html>
memberTable is defined as:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface name="memberTable"
displayName="A table for members of a community">
<composite:attribute name="memberList" required="true" />
<composite:attribute name="showPhone" type="java.lang.Boolean" default="false" />
<composite:attribute name="showRoles" type="java.lang.Boolean" default="false" />
<composite:attribute name="showAffiliation" type="java.lang.Boolean"
default="false" />
<composite:attribute name="showLastLoginDate" type="java.lang.Boolean"
default="false" />
<composite:attribute name="showActions" type="java.lang.Boolean"
default="false" />
<composite:attribute name="allowSortLastName" type="java.lang.Boolean"
default="false" />
<composite:attribute name="allowSortFirstName" type="java.lang.Boolean"
default="false" />
<composite:attribute name="allowSortEmail" type="java.lang.Boolean"
default="false" />
<composite:actionSource name="sortAction"
targets="dataTable:sortLastName dataTable:sortFirstName dataTable:sortEmail" />
<composite:actionSource name="actions" targets="dataTable:actions" />
</composite:interface>
<composite:implementation>
<div id="#{cc.clientId}" class="member-table">
<h:dataTable id="dataTable" value="#{cc.attrs.memberList}" var="member"
rowClasses="odd,even"
columnClasses="column1,column2,column3,column4,column5,column6,column7">
<h:column>
<f:facet name="header">
<h:commandLink id="sortLastName"
rendered="#{cc.attrs.allowSortLastName}">
<f:attribute name="sortBy" value="lastName" />
<span>#{i18n['last-name']}</span>
</h:commandLink>
<h:outputText rendered="#{not cc.attrs.allowSortLastName}"
value="#{i18n['last-name']}" />
</f:facet>
<span class='#{member.invalid ? "warning" : "" }'>#{member.lastName}</span>
</h:column>
<h:column>
<f:facet name="header">
<h:commandLink id="sortFirstName"
rendered="#{cc.attrs.allowSortFirstName}">
<f:attribute name="sortBy" value="firstName" />
<span>#{i18n['first-name']}</span>
</h:commandLink>
<h:outputText rendered="#{not cc.attrs.allowSortFirstName}"
value="#{i18n['first-name']}" />
</f:facet>
<span class='#{member.invalid ? "warning" : "" }'>#{member.firstName}</span>
</h:column>
<h:column>
<f:facet name="header">
<h:commandLink id="sortEmail"
rendered="#{cc.attrs.allowSortEmail}">
<f:attribute name="sortBy" value="email" />
<span>#{i18n['email-address']}</span>
</h:commandLink>
<h:outputText rendered="#{not cc.attrs.allowSortEmail}"
value="#{i18n['email-address']}" />
</f:facet>
<span class='#{member.invalid ? "warning" : "" }'>#{member.email}</span>
</h:column>
<h:column
rendered="#{cc.attrs.showPhone and loginUser.allowedToViewPhone}">
<f:facet name="header">#{i18n['phone-number']}</f:facet>
<span class='#{member.invalid ? "warning" : "" }'>#{member.phoneNumber}</span>
</h:column>
<h:column
rendered="#{cc.attrs.showRoles and loginUser.allowedToViewRoles}">
<f:facet name="header">#{i18n['roles']}</f:facet>
<span class='#{member.invalid ? "warning" : "" }'> <ui:repeat
value="#{member.roles}" var="role" varStatus="roleStatus">
<h:outputText rendered="#{roleStatus.index > 0}" value=", " />
#{role}
</ui:repeat>
</span>
</h:column>
<h:column
rendered="#{cc.attrs.showAffiliation and loginUser.allowedToViewAffiliation}">
<f:facet name="header">#{i18n['user-affiliation']}</f:facet>
<span class='#{member.invalid ? "warning" : "" }'>#{member.userAffiliation}</span>
</h:column>
<h:column
rendered="#{cc.attrs.showLastLoginDate and loginUser.allowedToViewLastLoginDate}">
<f:facet name="header">#{i18n['last-login-date']}</f:facet>
<h:outputText styleClass='#{member.invalid ? "warning" : "" }'
value="#{member.lastLoginDate}" converter="#{dateToWeeksOldConverter}" />
</h:column>
<h:column
rendered="#{cc.attrs.showActions and loginUser.allowedToViewActions}">
<f:facet name="header">#{i18n['actions']}</f:facet>
<h:commandLink id="actions">
<span>#{i18n['actions']}</span>
<f:attribute name="communityMember" value="#{member}" />
</h:commandLink>
</h:column>
</h:dataTable>
<h:outputText styleClass="warning" rendered="#{empty cc.attrs.memberList}"
value="#{i18n['no-records-found']}." />
</div>
</composite:implementation>
</html>
Here is the output:
Dec 6, 2012 11:11:08 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 3328 ms
11:23:01,616 INFO MemberController:43 - constructing MemberController
11:23:07,446 DEBUG MemberController:139 - getSortActionListener called
11:23:07,456 DEBUG MemberController:180 - constructing comparator map
11:23:07,466 DEBUG MemberController:213 - constructing SortActionListener
11:23:07,476 DEBUG MemberController:227 - Sorting by lastName Ascending (MemberController$SortActionListener#779d9c0d)
11:23:07,476 DEBUG MemberController:139 - getSortActionListener called
11:23:07,476 DEBUG MemberController:227 - Sorting by lastName Descending (MemberController$SortActionListener#779d9c0d)
11:23:12,116 DEBUG MemberController:127 - getActionsActionListener called
11:23:12,126 DEBUG MemberController:132 - action for homer#simpsons.tv
From the output, the first actionListener called twice, but the second one just once as expected.
This was run under tomecat 6.0.36 using jsf 2.1.13. If I use myfaces instead of jsf, don't have this problem.