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



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

findComponent()将客户端ID作为参数,而不是组件ID。客户端ID正是生成的与有问题的组件相关联的HTML id属性的值。在使用命令按钮的情况下,父级<h:form>的组件ID通常是前置的,由默认为:的命名容器分隔符分隔。

鉴于此,

<h:form id="form">
    <p:commandButton id="save" ... />
</h:form>

客户端ID将是CCD_ 5。

CommandButton button = (CommandButton) viewRoot.findComponent("form:save");

另请参阅关于识别和使用客户端ID的相关问题:如何找到ajax更新/渲染组件的客户端ID?找不到表达式为"的组件;foo";引用自";条";


与具体问题无关在Java端操作组件树是一种糟糕的做法。为此,您最好继续使用XHTML+XML,因为它比声明/定义树结构更具自文档性。您可以使用JSTL标记来动态构建视图(注意:这与使用rendered属性动态呈现视图不同!)。

例如

<p:commandButton ... action="#{bean.save}">
    <c:if test="#{bean.existing}">
        <f:actionListener binding="#{bean.needsUpdate()}" />
    </c:if>
</p:commandButton>

另请参阅JSF2 Facelets中的JSTL。。。有道理吗?

更重要的是,您可以将#{bean.existing}作为方法参数传递。

<p:commandButton ... action="#{bean.save(bean.existing)}" />

如果#{bean.existing}引用与#{bean.save}相同的bean,那么这两种方法都有点奇怪。你可以在#{bean.save}内部检查一下。

public void save() {
    if (existing) {
        // UPDATE
    } else {
        // INSERT
    }
}

进一步说,这不是IMO的责任,而是服务层的责任。您将整个实体传递给服务层,服务层根据PK检查实体是否存在。

if (entity.getId() == null) {
    // INSERT
} else {
    // UPDATE
}

最新更新