从bean访问PrimeFaces命令按钮以添加动作侦听器

时间:2016-04-10 20:13:40

标签: jsf primefaces jsf-2.2

我在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。

1 个答案:

答案 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
}