我在ID为“save”的视图中有以下命令按钮:
<p:panel style="border:none;text-align:left;margin:0;">
<p:commandButton value="Save Document" id="save" icon="fa fa-save"
disabled="#{dIGRCController.digrc.qconce == '020'}">
<f:param name="validate" value="true" />
</p:commandButton>
<p:commandButton value="Clear" icon="fa fa-undo"></p:commandButton>
</p:panel>
我正在尝试动态分配不同的actionListener。如果用户想要插入一些新记录,我希望它调用insert方法。如果用户想要更新现有记录,则应调用update方法。
现在我正在尝试这样做:
@PostConstruct
public void init() {
// setting the action listener of the Save Document button
UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();
// UIComponent button = viewRoot.findComponent("save");
CommandButton button = (CommandButton) viewRoot.findComponent("save");
FacesContext context = FacesContext.getCurrentInstance();
MethodExpression methodExpression = context
.getApplication()
.getExpressionFactory()
.createMethodExpression(context.getELContext(),
"#{dIGRCController.updateDocument}", null,
new Class[] { DIGRCController.class });
button.addActionListener(new MethodExpressionActionListener(
methodExpression));
}
我在行上得到一个空指针异常:
button.addActionListener(new MethodExpressionActionListener(
methodExpression));
我做错了什么?还有另一种方法可以完成我想要做的事情吗?我使用的是JSF 2.2,PrimeFaces 5.3和OmniFaces 1.11。
答案 0 :(得分:1)
findComponent()
将客户端ID作为参数而不是组件ID。客户端ID正是与所讨论的组件关联的生成的HTML id
属性的值。如果是命令按钮,通常会添加父<h:form>
的组件ID,由命名容器分隔符分隔,默认为:
。
鉴于此,
<h:form id="form">
<p:commandButton id="save" ... />
</h:form>
客户端ID为form:save
。
CommandButton button = (CommandButton) viewRoot.findComponent("form:save");
另请参阅有关识别和使用客户ID的相关问题:How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
对于具体问题 无关,在Java端操纵组件树是一种不好的做法。你最好继续使用XHTML + XML,这样就可以自我记录,而不是声明/定义树结构。您可以使用JSTL标记动态构建视图(注意:这与使用rendered
属性动态呈现视图不同!)。
E.g。
<p:commandButton ... action="#{bean.save}">
<c:if test="#{bean.existing}">
<f:actionListener binding="#{bean.needsUpdate()}" />
</c:if>
</p:commandButton>
另见JSTL in JSF2 Facelets... makes sense?
更重要的是,您可以将#{bean.existing}
作为方法参数传递。
<p:commandButton ... action="#{bean.save(bean.existing)}" />
如果#{bean.existing}
将同一个bean称为#{bean.save}
,那么这两种方法都会变得有些奇怪。你可以在#{bean.save}
内部检查它。
public void save() {
if (existing) {
// UPDATE
} else {
// INSERT
}
}
进一步说明,这是IMO不是前端层的责任,而是服务层的责任。您将整个实体传递给服务层,而服务层又根据PK检查它是否存在。
if (entity.getId() == null) {
// INSERT
} else {
// UPDATE
}