Please help to find out the problem.
I have two composite components:
ajaxCommandButton:
<cc:interface>
<cc:actionSource name="ajaxAction" targets="ajaxCmd" />
<cc:attribute name="action" targets="ajaxCmd" method-signature="void action()" />
<cc:attribute name="value" />
<cc:attribute name="title" />
</cc:interface>
<cc:implementation>
<h:commandButton value="#{cc.attrs.value}" id="ajaxCmd"
title="#{cc.attrs.title}" >
<f:ajax />
</h:commandButton>
</cc:implementation>
and treeItem:
<cc:interface>
<cc:actionSource name="itemAction" targets="ajaxAction" />
</cc:interface>
<cc:implementation>
<ccb:ajaxCommandButton value="test" action="#{action()}" id="ajaxAction">
<f:setPropertyActionListener for="ajaxAction" value="#{value}" target="#{beanProperty}" />
</ccb:ajaxCommandButton>
</cc:implementation>
and usage from ui:composition
<ccb:treeItem>
<f:setPropertyActionListener for="ajaxAction" value="#{value}" target="#{beanProperty}" />
</ccb:treeItem>
What right way to set actionSource from ui:composition to ccb:ajaxCommandButton ?
Thanks in advance!
Related
Is it possible to pass some sort of parametrized fragment/template to be reused inside a composite component?
<my:list value="#{someBean.ratios}" var="ratio">
<???>
<h:outputText value="#{ratio}">
<f:convertNumber type="percent" maxFractionDigits="2" minFractionDigits="2" />
</h:outputText>
</???>
</my:list>
with the following my:list component:
<ui:component>
<cc:interface>
<cc:attribute name="value" />
<cc:attribute name="var" />
</cc:interface>
<cc:implementation>
<ul>
<ui:repeat value="#{cc.attrs.value}" var="item">
<li>
<???insert body/fragment/template???>
<ui:param name="#{cc.attrs.var}" value="#{item}" />
</???insert body/fragment/template???>
</li>
</ui:repeat>
</ul>
</cc:implementation>
</ui:component>
UPDATE I have also tried something like that but it does not work:
<my:list value="#{someBean.ratios}">
<f:convertNumber type="percent" maxFractionDigits="2" minFractionDigits="2" for="output" />
</my:list>
with component defined as:
<ui:component>
<cc:interface>
<cc:attribute name="value" />
</cc:interface>
<cc:implementation>
<ul>
<ui:repeat value="#{cc.attrs.value}" var="item">
<li>
<h:outputText value="#{item}" id="output" />
</li>
</ui:repeat>
</ul>
</cc:implementation>
</ui:component>
I'm facing a problem using OmniFaces 2.1 o:validateBean with method="validateCopy" when my inputs are composite components. With method="validateActual", it validates as expected.
JSF implementation: Mojarra 2.2.8-jbossorg-1.
My composite component source:
<composite:interface>
<composite:attribute name="target" />
<composite:attribute name="label"/>
<composite:attribute name="value" />
<composite:attribute name="required" />
<composite:attribute name="size" />
<composite:attribute name="disabled" />
<composite:attribute name="styleInput" required="false" />
<composite:editableValueHolder name="input" targets="input" />
<composite:clientBehavior name="change" event="change" targets="input" />
<composite:clientBehavior name="keypress" event="keypress" targets="input" />
</composite:interface>
<composite:implementation>
<p:outputLabel id="label" for="input" value="#{cc.attrs.label}" />
<h:panelGrid columns="3">
<p:inputText id="input" value="#{cc.attrs.value}"
style="#{cc.attrs.styleInput}" size="#{cc.attrs.size}"
disabled="#{cc.attrs.disabled}" required="#{cc.attrs.required}">
</p:inputText>
<p:message for="input" display="icon">
<p:effect type="pulsate" event="load" delay="500" />
</p:message>
</h:panelGrid>
</composite:implementation>
I tracked down to the omnifaces source and got to the source point below, in the o:validateBean:
ValueReference valueReference = getValueReference(context.getELContext(), valueExpression);
if (valueReference.getBase().equals(base)) {
operation.run((EditableValueHolder) component, valueReference);
}
In a case where I use a simple input text, the valueReference().getBase() returns my to be validated bean. In a case where I use a composite component, the valueReference().getBase() returns a reference to CompositeComponentAttributesELResolver.ExpressionEvalMap.
Is threre a way to change my composite component so that it works with o:validateBean?
I working on custom JSF 2.2 components with corporate design.
I have a problem with input text.
The problem is that if I use my component and want to specify <h:message for="id_of_component"/> its not work. Because the id of component is different.
<h:message for="input"/>
<custom:input id="input" required="true"/>
If i specify it inside component it works but it's not what I want. It should be flexible in case anyone want to use message on diferent place than I specify in component.
Component definition (with message):
<!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:h="http://xmlns.jcp.org/jsf/html"
xmlns:cc="http://xmlns.jcp.org/jsf/composite"
xmlns:p="http://xmlns.jcp.org/jsf/passthrough">
<!-- INTERFACE -->
<cc:interface name="input" expert="true">
<cc:attribute name="id" required="false"/>
<cc:attribute name="label" />
<cc:attribute name="value" />
<cc:attribute name="title" />
<cc:attribute name="readonly" default="false" type="java.lang.Boolean" />
<cc:attribute name="required" default="false" type="java.lang.Boolean" />
<cc:attribute name="rendered" default="true" type="java.lang.Boolean" />
<cc:attribute name="placeholder" type="java.lang.String"/>
<cc:clientBehavior name="click" targets=":#{cc.id}" event="click" default="true"/>
<cc:clientBehavior name="change" targets=":#{cc.id}" event="change" default="true"/>
<cc:clientBehavior name="blur" targets=":#{cc.id}" event="blur" default="true"/>
<cc:clientBehavior name="keyup" targets=":#{cc.id}" event="keyup" default="true"/>
</cc:interface>
<cc:implementation>
<h:panelGrid rendered="#{cc.attrs.rendered}" columns="2" id="panel" styleClass="customInputWrapper">
<h:outputLabel title="#{cc.attrs.title}"
value="#{cc.attrs.label}#{cc.attrs.required ? ' *' : ''}" for="#{cc.attrs.id}" />
<h:inputText id="#{cc.attrs.id}" styleClass="customInput" value="#{cc.attrs.value}" p:placeholder="#{cc.attrs.placeholder}" readonly="#{cc.attrs.readonly}" title="#{cc.attrs.title}" required="#{cc.attrs.required}"/>
<h:message for="#{cc.attrs.id}" />
<h:outputStylesheet library="custom" name="customComponentsStyle.css"/>
</h:panelGrid>
</cc:implementation>
</html>
Do you have any solution how to solve this problem?
I have the following problem with nested composite components and passing validators to a inputtext in a nested component:
The wrapper custom component (wrapper.xhtml):
<cc:interface>
<cc:attribute name="value" required="false" />
</cc:interface>
<cc:implementation>
<h:panelGroup>
<h:outputLabel value="TEST:"/>
<temptest:input value="#{cc.attrs.value}">
<cc:insertChildren/>
</temptest:input>
</h:panelGroup>
</cc:implementation>
The nested custom component (input.xhtml):
<cc:interface>
<cc:attribute name="value" required="false" />
<cc:editableValueHolder name="input" targets="input" />
</cc:interface>
<cc:implementation>
<h:inputText value="#{cc.attrs.value}" id="input" >
<cc:insertChildren/>
</h:inputText>
</cc:implementation>
The trial to pass a validator to the nested custom component (pageXYZ.xhtml):
<h:form>
...
<temptest:wrapper value="#{bean.value}">
<f:validateRequired for="input"/>
</temptest:wrapper>
<!-- this works:
<temptest:input value="#{bean.value}">
<f:validateRequired for="input"/>
</temptest:input> -->
<h:message for="input"/>
...
</h:form>
Is there a way to pass (one or more) validators to a nested custom component?
I use composite component which has InputNumber from Primefaces extensions in its basis. I've set required attribute to true and message is not shown. Also I don't have * mark which indicates that the field is required.
Here is the code:
<p:outputLabel for="maxvrednost" value="#{resources['skale.maxvrednost']}" />
<asw:inputDecimal id="maxvrednost" bean="#{attrsBean}" column="maxvrednost" required="true" disabled="#{tip == 'brisanje'}" value="#{dto.maxvrednost}"/>
<p:message for="maxvrednost" display="icon" />
Code for composite component is:
<cc:interface>
<cc:attribute name="bean" required="true" type="asw.iis.common.ui.beans.CommonListBackingBean" />
<cc:attribute name="column" required="true" type="java.lang.String" />
<cc:attribute name="value" required="true" type="java.lang.Object" />
<cc:attribute name="disabled" default="false" required="false" type="java.lang.Boolean" />
<cc:attribute name="title" required="false" type="java.lang.String" default=""/>
</cc:interface>
<cc:implementation>
<pe:inputNumber emptyValue="" style="text-align: right;" value="#{cc.attrs.value}" required="#{cc.attrs.required}"
decimalSeparator="#{applicationPropertiesBean.decimalSeparator}" disabled="#{cc.attrs.disabled}"
decimalPlaces="#{cc.attrs.bean.findNumberOfDecimalPlaces(cc.attrs.column)}" title="#{cc.attrs.title}"
thousandSeparator="#{applicationPropertiesBean.groupSeparator}">
</pe:inputNumber>
</cc:implementation>
Not a 100% proper solution but it works for me:
<composite:interface >
<composite:attribute name="value" required="false" type="java.lang.String" default=""></composite:attribute>
<composite:attribute name="update" required="false" type="java.lang.String" default=""></composite:attribute>
<composite:attribute name="process" required="false" type="java.lang.String" default=""></composite:attribute>
<composite:attribute name="requiredMessage" required="false" type="java.lang.String" default=""></composite:attribute>
<composite:attribute name="decimalPlaces" required="false" type="java.lang.Integer" default="0"></composite:attribute>
<composite:editableValueHolder name="value" targets="num"></composite:editableValueHolder>
<composite:
</composite:interface>
<composite:implementation>
<div id="#{cc.clientId}">
<pe:inputNumber id="num" roundMethod="S" decimalPlaces="#{cc.attrs.decimalPlaces}" symbol="#{applicationBean.currentCurrencySymbol}"
minValue="0" required="true" requiredMessage="#{cc.attrs.requiredMessage}"
value="#{cc.attrs.value}"></pe:inputNumber>
</div>
</composite:implementation>
Use as follows:
<p:outputLabel value="Enter Amount" for="amt:num"></p:outputLabel>
<p:message for="amt:num"></p:message>
<comp:InputCurrency id="amt" roundMethod="S" decimalPlaces="0" symbol="#{applicationBean.currentCurrencySymbol}"
minValue="1" requiredMessage="#{loc._('Please enter amount to withdraw!')}"
value="#{myBean.amount}"></comp:InputCurrency>
Note that 'required' attribute is hardcoded to 'true'. If I define composite component attribute 'required' and copy the value to inputNumber 'required' property it behaves as required, but does not render the '*' mark on the label. This happens because inputNumber's 'required' attribute has not been set at render time, comes back as 'false' - not sure why, didnt have time to dig into this.