问题
Here is my (simplified) issue :
I've got a page that is using 2 composite components of mine :
- CCSelection
- CCDisplay
In CCSelection, I have a list of values, each one has got a h:commandLink onto.
When clicking on a link, the CCDiaplay component is refreshed using the selected value.
To do this, CCSelection exposes a method attribute that is directly linked on each h:commandLink. The value is given to the method using f:attribute.
In the page backing bean, I've got a method (that is given to CCSelection as an attribute), that sets a member.
CCDisplay gets this value though an cc:attribute via the pages's member's getter.
It works !
Now, I want to ajaxize this behaviour.
I tryed to put an f:ajax for each h:commandLink in CCSelection... but if I put @form or @all in the render attribute, nothing is rendered (but the setter methods are called). If I put the id of the UIComponent (of the Page) to render, I get a nullpointerexception saying that a property is not defined for NamingContainer in CCDisplay. Quite strange because I didn't change anything inside CCDisplay !
I think the solution is to put the f:ajax not inside CCSelection but in Page.
So there may be 2 ways to achieve this :
- CCSelection raises an event f:ajax can manage... but how ?
- Using cc:clientBehaviour for CCSelection. But is it possible to target more that 1
component (I've got many h:commandLink, but I want only 1 event).
- Other ways ?
Here is a pseudo code
page.xhtml
<myComp:ccSelection actionMethod="#{pageBean.select}"
render="#{clientIDHelper.clientId['display']}" />
<h:panelGroup id="diplay" binding="#{clientIDHelper.bindings['display']}">
<myComp:ccDisplay value="#{pageBean.value}" />
</h:panelGroup>
To recover the full clientid of the panel containing the ccDiaplay composite component, I use a clientIDMap technic described here.
PageBean.java
private String _value;
public String getValue() { return _value; }
public void setValue(String value) [ _value = value; }
public void select(String value) {
setValue(value);
}
ccSelection.xhtml
<cc:interface>
<cc:attribute method-signature="void selectAction(String)"
name="actionMethod" />
<cc:attribute name="render" />
</cc:interface>
<cc:implementation>
<t:dataTable value="#{cc.values}"
var="val"
...
>
<h:column>
<t:commandLink actionListener="#{cc.selectionValueListener}"
<f:ajax render="#{cc.attrs.render}" />
<f:attribute name="value"
value="#{val}" />
</t:commandLink>
</h:column>
</t:dataTable>
</cc:implementation>
ccSelection.java
public void selectionValueListener() {
// recover the attribute value
String value = event.getComponent().getAttributes().get("value");
// call the callback method of the page
FacesContext context = FacesContext.getCurrentInstance();
MethodExpression method = (MethodExpression) this.getAttributes().get("actionMethod");
if (method != null)
method.invoke(context.getELContext(), new Object[] {value});
}
I don't think ccDisplay is interressting.
So, if I don't put the f:ajax tag, it works.
When I put the f:ajax with the render pointing to the clientId passed in param, I get an error while loading the page.
If I change the render for @form or @all, the pageBean.select method is called, but ccDisplay is not refreshed.
回答1:
I think i see a little error in page.xhtml. See when you created the component cc:display you said:
<cc:attribute method-signature="void selectAction(String)" name="actionMethod" />
That means that a parameter is needed.
But when you call it in page.xhtml you do this:
<myComp:ccSelection actionMethod="#{pageBean.select}"...
And its backing bean method is:
public void select(String value) {
setValue(value);
}
As you see the backing bean is correct, but when you call the component in the page, there is no parameter being passed to the bean, and at the end the value is never set. I think that might be one of the reasons.
To fix it i think you should pass the value some how:
<myComp:ccSelection actionMethod="#{pageBean.select(???Selected value
???)}"...
回答2:
OK. It is solved... but I don't like it very much.
You'll think I'm a fool : I solved the problem by removing the <![CDATA surrounding my scripts !
I've already found some issue using CDATA. I don't know if this is a MyFaces bug or something I do the wrong way like putting many h:outputScript blocks with CDATA in composite components but with CDATA, I get errors or not working. Just removing it, it works !
来源:https://stackoverflow.com/questions/7931684/jsf2-composite-component-link-using-ajax