问题
I am calling valueChangeListener
on a <h:selectBooleanCheckbox>
which is inside a dataTable. and that dataTable is again inside another(outer) dataTable. In the valueChangeListener
method I want the instance object of outer dataTable. Is there any way to get the object of outer dataTable instance?
EX:
<h:panelGroup id="panelId">
<p:dataTable id="outerDatatable"
var="supplier"
value="bean.supplierList">
<p:column>
<f:facet name="header">
<h:outputText value="Suppliers" />
</f:facet>
<h:outputText value="#{supplier.name}" />
</p:column>
<p:column>
<p:dataTable id="innerDataTable"
var="supplierAccount"
value="supplier.supplierAccountList">
<p:column>
<h:selectBooleanCheckbox id="booleanBoxId"
value="#{supplierAccount.supported}"
valueChangeListener="#bean.checkBoxListener}"
immediate="true"
onchange="this.form.submit();"/>
</p:column>
</p:dataTable>
</p:column>
</p:dataTable>
</h:panelGroup>
I found the following solution : I used <p:ajax>
listener instead of valueChangeListener
, and I could pass 'supplier' object as well as supplierAccount
object to this listener method. We can pass any number of custom objects to <p:ajax>
listener.
<p:column>
<h:selectBooleanCheckbox id="booleanBoxId"
value="#{supplierAccount.supported}"
immediate="true">
</h:selectBooleanCheckbox>
<p:ajax listener="#{bean.myListenerMethod(supplier,supplierAccount)}"
update=":formName:panelId"/>
</p:column>
回答1:
In this particular case, you could get it by evaluating the #{supplier}
programmatically:
public void checkBoxListener(ValueChangeEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
Supplier supplier = context.getApplication().evaluateExpressionGet(context, "#{supplier}", Supplier.class);
// ...
}
However, this is plain ugly, you're synchronously submitting the entire form by onchange="submit()"
. I recommend to throw in some ajax for that.
<h:selectBooleanCheckbox value="#{supplierAccount.supported}">
<f:ajax listener="#{bean.checkBoxListener}" render="???" />
</h:selectBooleanCheckbox>
(the render
attribute is up to you)
with
public void checkBoxListener(AjaxBehavior event) {
Boolean value = (Boolean) ((UIInput) event.getComponent()).getValue();
FacesContext context = FacesContext.getCurrentInstance();
Supplier supplier = context.getApplication().evaluateExpressionGet(context, "#{supplier}", Supplier.class);
// ...
}
Or if your environment supports EL 2.2 and thus specifying method arguments in EL:
<h:selectBooleanCheckbox value="#{supplierAccount.supported}">
<f:ajax listener="#{bean.checkBoxListener(component, supplier)}" render="???" />
</h:selectBooleanCheckbox>
public void checkBoxListener(UISelectBoolean checkbox, Supplier supplier) {
boolean selected = checkbox.isSelected();
// ...
}
See also:
- When to use valueChangeListener or f:ajax listener?
Unrelated to the concrete problem, as to using onchange="submit()"
, it may be useful to know that onchange
doesn't work as expected for checkboxes in IE6/7. It get only fired on every 2nd click. You rather want to use onclick="submit()"
instead.
回答2:
I see that you forgot a brace ({) just before bean
:
valueChangeListener="#{bean.checkBoxListener}" immediate="true"
Also, since you're using Primefaces, you could use it's components(that if you use version 3): http://www.primefaces.org/showcase-labs/ui/selectBooleanCheckbox.jsf
It isn't necessary to use outputText if you use jsf 2:
<f:facet name="header">
Suppliers
</f:facet>
Also it isn't necessary to use f:facet
because the column
component has an attribute called headerText
:
<p:column headerText="Suppliers">
#{supplier.name}"
</p:column>
It's a lot simpler that way, isn't it?
PS: What's this? value="supplier.supplierAccountList"
No #{ }?
来源:https://stackoverflow.com/questions/8382579/how-to-pass-parameter-to-valuechangelistener-in-pdatatable