单击 CommandButton 在页面上动态实例化复合组件
Dynamically instantiate composite components on page, on clicking CommandButton
继传说中的 BalusC 对此 post 的回应之后:
How to programmatically or dynamically create a composite component in JSF 2
如果我有足够的分数,我会附上评论 post -- 但我没有足够的分数。
问题如下
我正在尝试设置一个 commandButton,它将 JSF 复合组件动态添加到 xhtml 文件。目的是多次单击它会将组件的多个实例放在页面上。
所以我在 XHTML 文件上有一个按钮:
<h:commandButton action="#{assessingController.addQuestion}" value="Add a Question"></h:commandButton>
调用 AssessingController 的方法:
public void addQuestion() {
UIComponent parent = null;
includeCompositeComponent(parent, "http://xmlns.jcp.org/jsf/composite/components", "questionComposite", "someId");
}
UIComponent parent = null;
—— 因为在传递到 includeCompositeComponent
之前必须以某种方式实例化或引用它。但如下所述 - 将其设置为 null 可能会导致空指针异常,(那么我应该怎么做呢?)
includeCompositeComponent
方法按照 BalusC 在上面 post:
中引用的 JSF 2.2 方法
public void includeCompositeComponent(UIComponent parent, String taglibURI, String tagName, String id) {
FacesContext context = FacesContext.getCurrentInstance();
UIComponent composite = context.getApplication().getViewHandler()
.getViewDeclarationLanguage(context, context.getViewRoot().getViewId())
.createComponent(context, taglibURI, tagName, null);
composite.setId(id);
parent.getChildren().add(composite);
}
当我点击 commandButton 时,记录如下:
javax.faces.el.EvaluationException: java.lang.NullPointerException
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:101)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
at javax.faces.component.UICommand.broadcast(UICommand.java:315) ...
Caused by: java.lang.NullPointerException
at controllers.AssessingController.includeCompositeComponent(AssessingController.java:123)
AssessingController.java:123 是这一行:
parent.getChildren().add(composite);
复合不为空(已检查)。
所以,很明显,也许 - parent 为空,这就是问题所在。
那么我怎样才能更好地参考 UIComponent
parent 开始呢?
我需要让它引用 xhtml 文件上的内容吗?我假设它需要某种占位符来充当 parent(?)。现在 xhtml 页面上只有 commandButton。
谢谢大家。
parent
应该表示您要在其中包含复合组件的组件。
想象一下,您最终想要以这种简单的 XHTML 表示形式结束:
<h:panelGroup id="questions">
<your:questionComposite />
</h:panelGroup>
然后您应该准确地提供 <h:panelGroup>
组件作为 parent
。
<h:form>
<h:commandButton ... action="#{bean.addQuestion}" />
</h:form>
<h:panelGroup id="questions" />
public void addQuestion() {
UIComponent parent = context.getViewRoot().findComponent("questions");
// ...
}
或者,通过传递具体组件本身:
<h:form>
<h:commandButton ... action="#{bean.addQuestion(questions)}" />
</h:form>
<h:panelGroup id="questions" binding="#{questions}" />
public void addQuestion(UIComponent parent) {
// ...
}
与具体问题无关:这里有一个 thinking/design 错误。您应该使用 <ui:repeat><your:compositeComponent>
,然后将 @ViewScoped
bean 提供给 <ui:repeat>
表示复合模型值的动态大小的实体列表。
<h:form>
<h:commandButton ... action="#{bean.addQuestion}" />
</h:form>
<ui:repeat value="#{bean.questions}" var="question">
<your:questionComposite value="#{question}" />
</ui:repeat>
private List<Question> questions;
public void addQuestion() {
questions.add(new Question());
}
任何时候您需要处理支持 bean 中的原始 UIComponent
实例,暂停一下并仔细研究或询问您是否真的以正确的方式做事。也许它属于支持组件,或者可以只用纯 XHTML 完成。
另请参阅:
- How to dynamically add JSF components
- How does the 'binding' attribute work in JSF? When and how should it be used?
继传说中的 BalusC 对此 post 的回应之后:
How to programmatically or dynamically create a composite component in JSF 2
如果我有足够的分数,我会附上评论 post -- 但我没有足够的分数。
问题如下
我正在尝试设置一个 commandButton,它将 JSF 复合组件动态添加到 xhtml 文件。目的是多次单击它会将组件的多个实例放在页面上。
所以我在 XHTML 文件上有一个按钮:
<h:commandButton action="#{assessingController.addQuestion}" value="Add a Question"></h:commandButton>
调用 AssessingController 的方法:
public void addQuestion() {
UIComponent parent = null;
includeCompositeComponent(parent, "http://xmlns.jcp.org/jsf/composite/components", "questionComposite", "someId");
}
UIComponent parent = null;
—— 因为在传递到 includeCompositeComponent
之前必须以某种方式实例化或引用它。但如下所述 - 将其设置为 null 可能会导致空指针异常,(那么我应该怎么做呢?)
includeCompositeComponent
方法按照 BalusC 在上面 post:
public void includeCompositeComponent(UIComponent parent, String taglibURI, String tagName, String id) {
FacesContext context = FacesContext.getCurrentInstance();
UIComponent composite = context.getApplication().getViewHandler()
.getViewDeclarationLanguage(context, context.getViewRoot().getViewId())
.createComponent(context, taglibURI, tagName, null);
composite.setId(id);
parent.getChildren().add(composite);
}
当我点击 commandButton 时,记录如下:
javax.faces.el.EvaluationException: java.lang.NullPointerException
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:101)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
at javax.faces.component.UICommand.broadcast(UICommand.java:315) ...
Caused by: java.lang.NullPointerException
at controllers.AssessingController.includeCompositeComponent(AssessingController.java:123)
AssessingController.java:123 是这一行:
parent.getChildren().add(composite);
复合不为空(已检查)。 所以,很明显,也许 - parent 为空,这就是问题所在。
那么我怎样才能更好地参考 UIComponent
parent 开始呢?
我需要让它引用 xhtml 文件上的内容吗?我假设它需要某种占位符来充当 parent(?)。现在 xhtml 页面上只有 commandButton。
谢谢大家。
parent
应该表示您要在其中包含复合组件的组件。
想象一下,您最终想要以这种简单的 XHTML 表示形式结束:
<h:panelGroup id="questions">
<your:questionComposite />
</h:panelGroup>
然后您应该准确地提供 <h:panelGroup>
组件作为 parent
。
<h:form>
<h:commandButton ... action="#{bean.addQuestion}" />
</h:form>
<h:panelGroup id="questions" />
public void addQuestion() {
UIComponent parent = context.getViewRoot().findComponent("questions");
// ...
}
或者,通过传递具体组件本身:
<h:form>
<h:commandButton ... action="#{bean.addQuestion(questions)}" />
</h:form>
<h:panelGroup id="questions" binding="#{questions}" />
public void addQuestion(UIComponent parent) {
// ...
}
与具体问题无关:这里有一个 thinking/design 错误。您应该使用 <ui:repeat><your:compositeComponent>
,然后将 @ViewScoped
bean 提供给 <ui:repeat>
表示复合模型值的动态大小的实体列表。
<h:form>
<h:commandButton ... action="#{bean.addQuestion}" />
</h:form>
<ui:repeat value="#{bean.questions}" var="question">
<your:questionComposite value="#{question}" />
</ui:repeat>
private List<Question> questions;
public void addQuestion() {
questions.add(new Question());
}
任何时候您需要处理支持 bean 中的原始 UIComponent
实例,暂停一下并仔细研究或询问您是否真的以正确的方式做事。也许它属于支持组件,或者可以只用纯 XHTML 完成。
另请参阅:
- How to dynamically add JSF components
- How does the 'binding' attribute work in JSF? When and how should it be used?