Использование postAddToView
, как BalusC написал в по этой ссылке , работает как положено. Я создаю компонент программным способом, добавляю к нему поведение ajax, компонент добавляется в дерево компонентов, добавляется идентификатор (например, если я пишу setId("uniqueId")
, я вижу на стороне клиента, что все родительские контейнеры именования добавляются - я получаю form:uniqueId
). Слушатель Ajax вызывается, и все обновляется, как и ожидалось.
Однако, если я повторяю то же самое, но на этот раз внутри таблицы данных PrimeFaces, выполняется рендеринг HTML, выполняется рендеринг JavaScript PrimeFaces, все остается таким же , за исключением , ни один из программно созданных компонентов не добавляется в дерево компонентов, и сгенерированный идентификатор клиента не добавляется (это не form:uniqueId
, а просто uniqueId
.
Есть идеи, как это решить? JSF 2.2 MyFaces, PrimeFaces 7.0, Omnifaces 2.7 WebSphere Liberty EE7.
<ui:composition template="WEB-INF/templates/main.xhtml">
<ui:define name="content">
<h:form id="form">
<p:dataTable id="table">
<f:event type="postAddToView" listener="#{myBean.populateDatatable}" />
<p:column>
<p:inputText value="#{myBean.testField}">
</p:inputText>
</p:column>
</p:dataTable>
</h:form>
<h:form id="form2">
<f:event type="postAddToView" listener="#{myBean.populateForm}" />
</h:form>
</ui:define>
</ui:composition>
Bean:
public void test() {
log.debug("Ajax listener is called!");
}
/* This is working fine! */
public void populateForm(ComponentSystemEvent event) {
FacesContext fc = FacesContext.getCurrentInstance();
Application application = fc.getApplication();
ExpressionFactory ef = application.getExpressionFactory();
ELContext elc = fc.getELContext();
HtmlForm form = (HtmlForm) event.getComponent();
UIInput input = new HtmlInputText();
input.setId("testInput"); // Must be unique!
ValueExpression valueExp = ef.createValueExpression(elc, "#{myBean.testField}", Object.class);
input.setValueExpression("value", valueExp);
AjaxBehavior ajax = (AjaxBehavior)application.createBehavior(AjaxBehavior.BEHAVIOR_ID);
ajax.setGlobal(false);
ajax.setProcess("@this");
ajax.setPartialSubmit(true);
ajax.setUpdate("@this");
ajax.setForm("form");
ajax.setListener(ef.createMethodExpression(elc, "#{myBean.test}", null, new Class[] {}));
input.addClientBehavior("change", ajax);
form.getChildren().add(input);
}
/* This is NOT working fine! */
public void populateDatatable(ComponentSystemEvent event) {
DataTable table = (DataTable) event.getComponent();
List<UIColumn> columns = new ArrayList<>();
UIComponentBase[] datatableComponentRow1 = new UIComponentBase[someList.size()];
FacesContext fc = FacesContext.getCurrentInstance();
Application application = fc.getApplication();
ExpressionFactory ef = application.getExpressionFactory();
ELContext elc = fc.getELContext();
for (int i = 0; i < someList.size(); i++) {
HtmlOutputText text = (HtmlOutputText)application.createComponent(HtmlOutputText.COMPONENT_TYPE);
text.setValue(someList.get(i).getSomeField());
text.setId("out_" + i);
InputText inputText = (InputText)application.createComponent(InputText.COMPONENT_TYPE);
inputText.setId("input_" + i);
ValueExpression valueExp = ef.createValueExpression(elc, "#{myBean.someList[" + i + "].someInputFieldFromThatList}", Object.class);
inputText.setValueExpression("value", valueExp);
AjaxBehavior ajax = (AjaxBehavior)application.createBehavior(AjaxBehavior.BEHAVIOR_ID);
ajax.setGlobal(false);
ajax.setProcess("@this");
ajax.setPartialSubmit(true);
ajax.setUpdate("@this");
ajax.setForm("form");
ajax.setListener(ef.createMethodExpression(elc, "#{myBean.test}", null, new Class[] {}));
inputText.addClientBehavior("change", ajax);
HtmlPanelGrid panelGrid = (HtmlPanelGrid)application.createComponent(HtmlPanelGrid.COMPONENT_TYPE);
panelGrid.setId("grid_" + i);
panelGrid.getChildren().add(text);
panelGrid.getChildren().add(inputText);
Column column = (Column)application.createComponent(Column.COMPONENT_TYPE);
column.setId("col_" + i);
column.setHeaderText(someList.get(i).getSomeFieldFromThatListForColumnHeader());
column.getChildren().add(panelGrid);
columns.add(column);
}
List<UIComponentBase[]> mockListSoWeGetOneRowInDatatable = new ArrayList<>();
mockListSoWeGetOneRowInDatatable.add(uiComponentsArrayOfSameLengthAsNumberOfColumns);
/* This is ALSO working fine - that single p:column in XHTML file - here i add ajax behaviour to it's inputText programmaticaly*/
AjaxBehavior ajax = (AjaxBehavior)application.createBehavior(AjaxBehavior.BEHAVIOR_ID);
ajax.setGlobal(false);
ajax.setProcess("@this");
ajax.setPartialSubmit(true);
ajax.setUpdate("@this");
ajax.setForm("form");
ajax.setListener(ef.createMethodExpression(elc, "#{myBean.test}", null, new Class[] {}));
((InputText)table.getColumns().get(0).getChildren().get(0)).addClientBehavior("change", ajax);
table.getColumns().addAll(columns);
table.setValue(mockListSoWeGetOneRowInDatatable);
}