正如Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes 的答案中所述,您应该使用:
<h:commandButton ...>
<f:ajax execute="childForm2:clientId1 childForm2:clientId2 ..."/>
</h:commandButton>
正如您已经提到的,这可能会导致令人痛苦的长且无法维护的字符串。在 PrimeFaces 中,您可以使用 @(...) 对您想要处理的输入进行 jQuery 处理。在普通的 JSF 中没有这样的东西。
您可以做的是在实用程序 bean 中创建一个方法,让您在特定组件中输入clientIds。 OmniFaces Components 实用程序类在这里派上用场:
public String inputClientIds(String clientId)
{
UIComponent component = Components.findComponent(clientId);
List<String> clientIds = new ArrayList<>();
for (UIInput input : Components.findComponentsInChildren(component, UIInput.class)) {
clientIds.add(input.getClientId());
}
return String.join(" ", clientIds);
}
现在您可以在您的 XHTML 中使用它,例如:
<h:commandButton ...>
<f:ajax execute="#{ajaxBean.inputClientIds('childForm2')}"/>
</h:commandButton>
如果您正在寻找纯 JSF/非 OmniFaces 解决方案,事情会变得更加冗长:
public String inputClientIds(String clientId)
{
UIComponent component = FacesContext.getCurrentInstance().getViewRoot().findComponent(clientId);
List<String> clientIds = new ArrayList<>();
for (UIInput input : findChildsOfType(component, UIInput.class)) {
clientIds.add(input.getClientId());
}
return String.join(" ", clientIds);
}
public static <C extends UIComponent> List<C>
findChildsOfType(UIComponent component,
Class<C> type)
{
List<C> result = new ArrayList<>();
findChildsOfType(component, type, result);
return result;
}
private static <C extends UIComponent> void
findChildsOfType(UIComponent component,
Class<C> type,
List<C> result)
{
for (UIComponent child : component.getChildren()) {
if (type.isInstance(child)) {
result.add(type.cast(child));
}
findChildsOfType(child, type, result);
}
}
您可以考虑使用一些实用方法创建一个类。