JSF2 commandButton 操作未在更新的片段中调用

Posted

技术标签:

【中文标题】JSF2 commandButton 操作未在更新的片段中调用【英文标题】:JSF2 commandButton action not invoked in an updated fragment 【发布时间】:2015-04-29 22:22:30 【问题描述】:

我在表单中有命令按钮。那些在页面加载时呈现的是调用动作, 但是<p:fragment> 标记中的那两个在回发时呈现并且不起作用。

<h:form>
    <p:commandButton action="#bean.actionA()"/>
    <p:commandButton actionListener="#bean.actionB()"/>

    <p:fragment rendered="#not empty bean.field">
        <p:commandButton action="#bean.actionA()"/>
        <p:commandButton actionListener="#bean.actionB()"/>
    </p:fragment>

    <ui:include ..>
        ...
        <p:commandLink update="@form">
            <i class="fa fa-folder"></i>
            <f:setPropertyActionListener value="#data.document" target="#bean.field" />
        </p:commandLink>
    </ui:include>
</h:form>

我是 JSF 的菜鸟。我知道这个问题与 JSF 生命周期有关,但我找不到可行的解决方案。

我的 bean 是视图范围,我使用 primefaces 5.1。

这是假设工作还是我使用了错误的方法来显示/隐藏按钮?

谢谢。

编辑:

经过一些测试,它接缝即使在调用操作时也会在带有null==bean.field 的 bean 上调用。 这对我来说没有意义,因为在更新完成并显示隐藏按钮后,我得到了渲染值 #bean.field.name

我错过了什么?

update=@form 更改为update=@all 时效果相同。

感谢任何帮助。

我的具有会话范围的 bean 很喜欢这个。在这种情况下,SessionScoped 按钮正在工作。为什么视图范围不够?

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;
import javax.faces.view.ViewScoped;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

//TODO: change to @ViewScoped
@ManagedBean(name="bean")
@SessionScoped
public class Bean extends BeanBase 

private static final long serialVersionUID = 1L;
    private static final Logger LOGGER = LogManager.getLogger(Bean.class.getName());

    @PostConstruct
    protected void init() 
        super.init();
    

    public void actionA() 
        LOGGER.debug("Action A triggerd!");
    
    public void actionB( ActionEvent event) 
        LOGGER.debug("Action B event triggerd!");
        super.edit(event);
    

【问题讨论】:

@stg 还是同样的问题。当我用p:outputPanelf:subview 替换p:fragment 时,按钮不会触发。 正如here 所写,它应该适用于“update=@form”。这正是我正在做的。我的表单更新是从复合组件调用的。但它的工作原理是显示隐藏的按钮。但是按钮操作没有正确设置。 @stg 我如何测试那个和哪个表达式。如何找到它? Bean 在视图范围内。它适用于工作按钮的操作, @stg 我已经用bean.field setter 和 update 调用更新了代码。我尝试了日志记录,但我不知道如何将它们分成 JSF 阶段。在页面加载时,我有 12 个 'bean.field' getter,其中 3 个为空。单击按钮时,我有 3 个 null 返回 getter cal。不同之处仅在于在一种情况下触发了对 bean 的操作。希望这会有所帮助。 它接缝即使在调用操作时也会在带有null==bean.field 的bean 上调用。我错过了什么? 【参考方案1】:

首先,p:fragment 标签应该用于在 AJAX 调用期间部分提交和处理表单的片段,而无需直接在相应的组件上明确定义此行为。如果您只想对一组组件进行强制渲染,最好只使用 p:outputPanel

但是这里导致问题的原因是,不仅在必须呈现表单时评估呈现的属性,而且在处理表单时也会评估。如果由于某种原因,渲染属性中的表达式现在被评估为false,则处理表单将停止并且不会调用操作。只是出于安全原因。

在您的情况下,field 在表单被预处理时被评估为null,因此您的 commandButton 父级的呈现属性被评估为false,这就是不调用操作方法的原因。

这样做的原因是,您的 ManagedBean 的范围由于某种原因太小和/或在渲染响应阶段后被销毁,因此,当您单击命令按钮时,您完全使用从未设置过 field 值的托管 bean 的新实例。

正如您所料,您的 ManagedBean 很可能在请求范围而不是视图范围内。检查您是否使用了正确的注释,将 Bean 置于正确的范围内,并且您没有混淆 JSF 和 CDI 注释。

【讨论】:

我使用@ViewScoped注解和import javax.faces.view.ViewScoped;。我认为应该这样做。好吧,它没有。你是对的,范围应该更大。当我更改为SessionScoped 时,它可以工作。为什么视图范围不够? @ViewScoped 应该足够广泛,如果你正确使用它的话。出于某种原因,您的 ViewScoped bean 无论如何都会被销毁。确保在单击 commandLink 时进行真正的 AJAX 调用而没有任何重定向。但是发布的代码中不存在您的问题。如果您希望我们调查您的 VewScoped bean 行为的原因,您必须提供一个完整的工作示例,说明问题真正发生的位置。 在这种情况下,我可以向您发送一小部分活动代码。很少有文件可以看。目前从项目中制作一个工作示例非常耗时。 我添加了一张图片,显示没有使用重定向。如果您有时间,我可以给您发送一个包含一些代码片段的 zip 文件供您查看。感谢您的努力。

以上是关于JSF2 commandButton 操作未在更新的片段中调用的主要内容,如果未能解决你的问题,请参考以下文章

h:button 和 h:commandButton 之间的区别

两个不同的 h:commandButton 动作的条件渲染

h:button和h:commandButton之间的区别

f:viewAction 被忽略,当 commandButton 导航到页面时

使用h:commandButton阻止p:对话框关闭

PrimeFaces commandButton 无法导航或更新