I try to bind component inside dynaFormControl but there is an error.
The code :
<pe:dynaForm id="dynaForm" value="#{dynaFormController.model}" var="data">
<pe:dynaFormControl type="input" for="txt" >
<p:inputText id="txt" value="#{data.value}" binding="#{data.in}" />
</pe:dynaFormControl>
</pe:dynaForm>
in is an InputText object, and when I run it, the page give this error :
/dynamic.xhtml #18,81 binding="#{data.in}": Target Unreachable,
identifier 'data' resolved to null
Related
Why can't I pass event name as argument to a composite component bean in JSF 2.
This works:
<f:ajax event="click"
render="#{cc.attrs.ajaxRender}"
execute="#{cc.attrs.ajaxExecute}"
immediate="#{cc.attrs.immediate}"/>
This doesn't:
<f:ajax event="#{cc.attrs.itemEvent}"
render="#{cc.attrs.ajaxRender}"
execute="#{cc.attrs.ajaxExecute}"
immediate="#{cc.attrs.immediate}"/>
Question is: why?
NOTE: eventName is actually defined in cc:interface as the following:
<composite:attribute name="itemEvent" default="click"/>
I have a composite (X) like this:
<composite:interface>
<composite:attribute name="textValue" />
<composite:attribute name="textValueChangeListner"
method-signature="void valueChanged(javax.faces.event.ValueChangeEvent)" />
<composite:implementation>
<ice:inputText
value="#{cc.attrs.textValue}"
valueChangeListener="#{cc.attrs.textValueChangeListner}"/>
In the JSF page I have something like:
<X:iText
textValue="#{cardBean.getCardValue}"
textValueChangeListner="#{cardHandler.cardValueChanged}" />
The above code works fine. But it does not work when NO "textValueChangeListner" is passed to the composite from JFace page; i.e:
<X:iText
textValue="#{cardBean.getCardValue}" />
Error I got:
[javax.enterprise.resource.webcontainer.jsf.lifecycle] Unable to resolve composite component from using page using EL expression '#{cc.attrs.textValueChangeListner}': javax.faces.FacesException: Unable to resolve composite component from using page using EL expression '#{cc.attrs.textValueChangeListner}'
In my scenario it is necessary that page developer may or may not supply the "textValueChangeListner" to the composite component.
How can I achieve that ?
Rename the attribute to valueChangeListener and use targets attribute,
<composite:attribute name="valueChangeListner"
method-signature="void valueChanged(javax.faces.event.ValueChangeEvent)"
targets="text" />
where text is the ID of the target input component,
<ice:inputText id="text" ... />
and remove the valueChangeListener from it.
You have two options here: First one is the easy way, just render another input text without having a valueChangeListener if the user didn't supply Value Change listener.
<ice:inputText
value="#{cc.attrs.textValue}"
valueChangeListener="#{cc.attrs.textValueChangeListener}"
rendered="#{!empty cc.attrs.textValueChangeListener}"/>
If you need to have a valueChangeListener in any case then apply an default value for the attribute:
<composite:attribute name="textValueChangeListener"
method-signature="void valueChanged(javax.faces.event.ValueChangeEvent)"
required="false"
default="#{cc.valueChangedListener}" />
For doing this you need to bind your composite component to a backing bean. And you need to define components' backing bean type through its interface declaration like this:
<composite:interface componentType="yourComponentBean">
<composite:attribute name="textValueChangeListener"
method-signature="void valueChanged(javax.faces.event.ValueChangeEvent)"
required="false"
default="#{cc.valueChangedListener}" />
</composite:interface>
And here is yourComponentBean which implements the default ValueChangedListener.
#FacesComponent("yourComponentBean")
public class YourComponentCC extends UINamingContainer
{
public void valueChangedListener(ValueChangeEvent ev)
{
....
}
}
Btw cc is a shortcut in EL to access backing bean that is defined as the componentType in your component. so cc.valueChangedListener will call valueChangedListener method defined in YourComponentCC class.
I have an inputText:
<h:inputText id="result" value="#{guessNumber.result}"/>
and another inputText:
<h:inputText id="name" value="#{guessNumber.named}" onchange="submit()" valueChangeListener="#{guessNumber.processValueChange}"/>
and inside the processValueChange method, I added the following line:
result = "hello";
but the displayed value of "result" inputText remains unchainged, what is the problem?
The valueChangeListener method isn't intended to make changes to the model this way. It's intented to listen on the actual change of the model value, at exactly the moment where you have a hand of both the old and new model value. For example, to perform some logging. It runs at the end of the validations phase, right before the update model values phase. So any changes which you make to the model values yourself inside the listener method would be overridden during the update model values phase.
You need a <f:ajax listener> instead. This runs during the invoke action phase, which is after the update model values phase.
<h:outputText id="result" value="#{guessNumber.result}" />
<h:inputText id="name" value="#{guessNumber.named}">
<f:ajax listener="#{guessNumber.namedChanged}" render="result" />
</h:inputText>
(note that I've removed the onchange="submit()" JavaScript handler!)
with
public void namedChanged(AjaxBehaviorEvent event) {
result = "Hello, you entered " + named;
}
(the argument is optional; if you don't need it, just omit it)
See also:
When to use valueChangeListener or f:ajax listener?
I found the solution:
Instead of binding the value attribute of the inputText to a String property (result) inside the bean, I bound the inputText to UIInput property inside the bean:
<h:inputText id="result" binding="#{guessNumber.result}"/>
and in the bean:
private UIInput result = null;
this lets the listener method modify the inputText value directly, instead of modifying the property that is bound to the value attribute of the inputText:
result.setValue("Hello");
Thanks for every one tried to solve my problem.
we are still in a JSF 1.2 to 2.0 migration scenario and we are now facing a problem related to c:set or ui:param variables used inside an EL expression.
Here are the facts. There is a button as composite component:
<cc:interface name="button" shortDescription="A button.">
...
<cc:attribute
name="disabled"
required="false"
default="false"
shortDescription="The disabled flag." />
...
</cc:interface>
<cc:implementation>
<ice:commandButton
...
disabled="#{cc.attrs.disabled}"
... />
</cc:implementation>
Now we are trying to use this button component inside a toolbar. The disabled state of the button is determined inside the toolbar using a c:set or a ui:param (we already tried both ways).
<c:set var="isButtonEnabled" value="#{backingBean.buttonEnabled}" />
or
<ui:param name="isButtonEnabled" value="#{backingBean.buttonEnabled}" />
#{isButtonEnabled}
<ctrl:button
...
disabled="#{!isButtonEnabled}"
... />
So here is our problem. If we simple print out the value of "isButtonEnabled" in the toolbar, it is always correct. So the backing bean is ok. But when we try to pass this value to the composite component, it is not working. "Disabled" is always evaluated to false.
Sure we could pass the method expression directly (#{!backingBean.isButtonEnabled}) and this will work fine. But in our scenario the determination of the enabled-flag is much more complicated and I just tried to keep the example as simple as possible. Aditionally this flag is used for multiple buttons inside the toolbar, so we wanted to keep the code maintainable by using a c:set or ui:param. Is this the wrong way to handle this? What do you recommend?
Thanks in advance.
SlimShady
Your problem is the way value binding is done in JSF. The prefered way is to retrieve the EL Expression an attribute was populated with by invoking getValueExpression("attributeName"). Then this EL Expression can be used to get or set the value in the backing bean. As your not passing #{!isButtonEnabled} but #{cc.attrs.disabled} to ice:commandButton the binding fails.
I solved this for the p:selectOneMenu component of Primefaces by writing a wrapping UIComponent which defines a property wrappedValue and passed that property to the p:selectOneMenu. In the getter and setter of that property I then used getValueExpression to retieve the real EL Expression for the attribute.
<composite:interface componentType="de.gw2tome.component.valuewrapper">
<composite:attribute name="value" type="de.gw2tome.models.Rarity"
required="true" />
</composite:interface>
<composite:implementation>
<p:selectOneMenu value="#{cc.wrappedValue}"/>
...
</composite:implementation>
#FacesComponent("de.gw2tome.component.valuewrapper")
public class ValueWrapper extends UINamingContainer {
public void setWrappedValue(Object wrappedValue) {
ValueExpression expr = getValueExpression("value");
ELContext ctx = getFacesContext().getELContext();
expr.setValue(ctx, wrappedValue);
}
public Object getWrappedValue() {
ValueExpression expr = getValueExpression("value");
ELContext ctx = getFacesContext().getELContext();
return expr.getValue(ctx);
}
}
The component can now be used the following way:
<g:rarityChooser value="#{itemSearchBean.minRarity}" />
I'm getting this error java.util.NoSuchElementException when i tried to check one of my checkbox under h:selectManycheckBox when i submit the form.
The many checkbox is dynamically populated from the bean. Here is my code.
<h:form id="eF">
<h:inputText id="i" value="#{aklat.suggest}">
<a4j:support event="onkeyup" action="#{aklat.complete}" reRender="m"></a4j:support>
</h:inputText>
<s:div>
<h:selectManyCheckbox value="#{aklat.selectedBooks}" layout="pageDirection" id="m">
<s:selectItems value="#{aklat.books}" var="_book" itemLabel="#{_book}" itemValue="#{_book}" label="#{_book.bookName}"/>
</h:selectManyCheckbox>
<a4j:commandButton value="Add Users" action="#{aklat.fire}"></a4j:commandButton>
</s:div>
</h:form>
The weird part is it renders some data output but when i checked the source code. there are no input type checkbox element.
Is something I am missing.
I assume your managed bean is request scope...
because you are making an ajax request, you have to enable "aklat.books" to persist its value longer than request but shorther than session scope.
If you have tomahawk between your app libraries you can use savestate like this (put it after the h:form tag) :
<t:saveState value="#{aklat.books}"/>
if no tomahawk, you can use a4j:keepAlive:
<a4j:keepAlive beanName = "#{aklat.books}"/>