I am currently trying to dynamically add a new component to the JSF component tree during an ajax request.
我目前正在尝试在ajax请求期间动态地向JSF组件树添加新组件。
In fact I add a child to the UIViewRoot component in my AjaxBehaviorListener which is fired on server side during the ajax request process.
实际上,我将一个子项添加到AjaxBehaviorListener中的UIViewRoot组件,该组件在ajax请求过程中在服务器端触发。
The issue is that the new component is not rendered. It seems that this component is not taken into account in the render response phase.
问题是不会渲染新组件。似乎在渲染响应阶段不考虑此组件。
Could you help me on this issue ?
你能帮我解决这个问题吗?
Regards,
问候,
Guillaume
纪尧姆
3 个解决方案
#1
2
This solution works in case of you know before the ajax request the component to add. But if you are not able to know which component to add, it does not work.
在ajax请求添加组件之前,您可以知道此解决方案。但是,如果您无法知道要添加哪个组件,则它不起作用。
I maybe found a solution :
我可能找到了解决方案:
My solution is to implement my custom PartialViewContext and use the method startInsertAfter or startInsertBefore of the PartialResponseWriter.
我的解决方案是实现我的自定义PartialViewContext并使用PartialResponseWriter的方法startInsertAfter或startInsertBefore。
It is working, but you have to put the component added as transient. (uiComponent.setTransient(Boolean.TRUE);)
它正在工作,但您必须将组件添加为瞬态。 (uiComponent.setTransient(Boolean.TRUE);)
Regards,
问候,
Guillaume
纪尧姆
#2
2
This works for me:
这对我有用:
Bean holding binding to UIComponent under which you want to add other UIComponents dynamically should be request scoped otherwise it can throw some nasty exceptions (don't ask me why):
Bean持有绑定到UIComponent,你想在其下动态添加其他UIComponents应该是请求作用域,否则它会抛出一些讨厌的异常(不要问我为什么):
@ManagedBean
@RequestScoped
public class AddressEditorBean {
// session bean reference for holding id number line and model
@ManagedProperty(value = "#{addressValueBean}")
private AddressValueBean address;
public String addOutputText() {
HtmlOutputText text = new HtmlOutputText();
int c = address.getC();
text.setValue("new text! " + c);
text.setId("id" + c++);
address.setC(c); // hold id number line in sessionbean
address.getComps().add(text); // hold new uicomponent in session bean to be able to rebuild it
panel.getChildren().clear(); // need to clear children and add them all again,
panel.getChildren().addAll(address.getComps()); // otherwise there are problems with duplicate children (bug?)
return "success";
}
public HtmlPanelGroup getPanel() {
return panel;
}
public void setPanel(HtmlPanelGroup pane) {
if (panel == null) {
this.panel = pane;
if (panel != null) {
panel.getChildren().addAll(address.getComps());
}
} else {
this.panel = pane;
}
}
}
code snippet from page. I dynnamically add components to <h:panelGroup>
来自页面的代码段。我动态地将组件添加到
<h:form>
<h:panelGroup id="section" binding="#{addressEditorBean.panel}">
</h:panelGroup>
<h:commandButton value="add new text" action="#{addressEditorBean.addOutputText}">
<f:ajax execute="@this" render="section" event="action"/>
</h:commandButton>
</h:form>
In Session bean I hold actual dynamic model so that I can rebuild it after page reload:
在Session bean中,我持有实际的动态模型,以便在页面重新加载后重建它:
@ManagedBean
@SessionScoped
public class AddressValueBean extends ValueBean<Address> {
private int c = 0;
private List<UIComponent> comps = new ArrayList<UIComponent>();
public AddressValueBean() {
setValue(new Address());
}
public int getC() {
return c;
}
public void setC(int cn) {
this.c = cn;
}
public List<UIComponent> getComps() {
return comps;
}
public void setComps(List<UIComponent> comps) {
this.comps = comps;
}
}
#3
1
Instead of trying to add the component dynamically during the ajax request, try defining the component upfront, and setting it's rendered tag to false. The contents of the component can then be populated with the ajax request, and the rendered attribute flipped to display the attribute.
而不是尝试在ajax请求期间动态添加组件,尝试预先定义组件,并将其呈现标记设置为false。然后可以使用ajax请求填充组件的内容,并翻转呈现的属性以显示该属性。
#1
2
This solution works in case of you know before the ajax request the component to add. But if you are not able to know which component to add, it does not work.
在ajax请求添加组件之前,您可以知道此解决方案。但是,如果您无法知道要添加哪个组件,则它不起作用。
I maybe found a solution :
我可能找到了解决方案:
My solution is to implement my custom PartialViewContext and use the method startInsertAfter or startInsertBefore of the PartialResponseWriter.
我的解决方案是实现我的自定义PartialViewContext并使用PartialResponseWriter的方法startInsertAfter或startInsertBefore。
It is working, but you have to put the component added as transient. (uiComponent.setTransient(Boolean.TRUE);)
它正在工作,但您必须将组件添加为瞬态。 (uiComponent.setTransient(Boolean.TRUE);)
Regards,
问候,
Guillaume
纪尧姆
#2
2
This works for me:
这对我有用:
Bean holding binding to UIComponent under which you want to add other UIComponents dynamically should be request scoped otherwise it can throw some nasty exceptions (don't ask me why):
Bean持有绑定到UIComponent,你想在其下动态添加其他UIComponents应该是请求作用域,否则它会抛出一些讨厌的异常(不要问我为什么):
@ManagedBean
@RequestScoped
public class AddressEditorBean {
// session bean reference for holding id number line and model
@ManagedProperty(value = "#{addressValueBean}")
private AddressValueBean address;
public String addOutputText() {
HtmlOutputText text = new HtmlOutputText();
int c = address.getC();
text.setValue("new text! " + c);
text.setId("id" + c++);
address.setC(c); // hold id number line in sessionbean
address.getComps().add(text); // hold new uicomponent in session bean to be able to rebuild it
panel.getChildren().clear(); // need to clear children and add them all again,
panel.getChildren().addAll(address.getComps()); // otherwise there are problems with duplicate children (bug?)
return "success";
}
public HtmlPanelGroup getPanel() {
return panel;
}
public void setPanel(HtmlPanelGroup pane) {
if (panel == null) {
this.panel = pane;
if (panel != null) {
panel.getChildren().addAll(address.getComps());
}
} else {
this.panel = pane;
}
}
}
code snippet from page. I dynnamically add components to <h:panelGroup>
来自页面的代码段。我动态地将组件添加到
<h:form>
<h:panelGroup id="section" binding="#{addressEditorBean.panel}">
</h:panelGroup>
<h:commandButton value="add new text" action="#{addressEditorBean.addOutputText}">
<f:ajax execute="@this" render="section" event="action"/>
</h:commandButton>
</h:form>
In Session bean I hold actual dynamic model so that I can rebuild it after page reload:
在Session bean中,我持有实际的动态模型,以便在页面重新加载后重建它:
@ManagedBean
@SessionScoped
public class AddressValueBean extends ValueBean<Address> {
private int c = 0;
private List<UIComponent> comps = new ArrayList<UIComponent>();
public AddressValueBean() {
setValue(new Address());
}
public int getC() {
return c;
}
public void setC(int cn) {
this.c = cn;
}
public List<UIComponent> getComps() {
return comps;
}
public void setComps(List<UIComponent> comps) {
this.comps = comps;
}
}
#3
1
Instead of trying to add the component dynamically during the ajax request, try defining the component upfront, and setting it's rendered tag to false. The contents of the component can then be populated with the ajax request, and the rendered attribute flipped to display the attribute.
而不是尝试在ajax请求期间动态添加组件,尝试预先定义组件,并将其呈现标记设置为false。然后可以使用ajax请求填充组件的内容,并翻转呈现的属性以显示该属性。