PrimeFaces CommandButton 操作未在 Composite 内调用

发布于 2024-12-11 09:27:39 字数 5627 浏览 1 评论 0原文

在下面的代码中,jsf html commandButton 操作被完美调用。 但 primefaces commandButton 操作未被调用。

<ui:component          
              xmlns="http://www.w3.org/1999/xhtml" 
            xmlns:f="http://java.sun.com/jsf/core"
            xmlns:h="http://java.sun.com/jsf/html"
           xmlns:ui="http://java.sun.com/jsf/facelets"
            xmlns:p="http://primefaces.prime.com.tr/ui"
    xmlns:composite="http://java.sun.com/jsf/composite">

    <composite:interface>
        <composite:attribute 
            name="managedBean"          
            type="java.lang.Object"
            required="true">                    
        </composite:attribute>
    </composite:interface>

    <composite:implementation>
        <f:view contentType="text/html"> 
            <h:form id="componentes">  
                <h:panelGrid columns="3">
                    <h:panelGroup>              
                        <h:outputText 
                              escape = "false" 
                               value = "#{cc.attrs.managedBean['value']}"       
                            rendered = "#{!cc.attrs.managedBean['editing']}"/> 
                        <p:editor 
                            widgetVar = "editor" 
                                value = "#{cc.attrs.managedBean.value}" 
                             rendered = "#{cc.attrs.managedBean.editing}"/>
                    </h:panelGroup>
                    <!-- ACTION IS CALLED -->                                 
                    <h:commandButton 
                                action = "#{cc.attrs.managedBean.toogleEditing}" 
                                 value = "#{cc.attrs.managedBean.editing?'Back':'Edit'}" 
                                update = "componentes"/>

                                    <!-- ACTION IS NOT CALLED -->           
                    <p:commandButton 
                                action = "#{cc.attrs.managedBean.toogleEditing}" 
                                 value = "#{cc.attrs.managedBean.editing?'Back':'Edit'}" 
                                update = "componentes"/>
                </h:panelGrid>
            </h:form>                    
        </f:view>
    </composite:implementation>
</ui:component>

如果将相同的代码放置在复合体(普通的 xhtml 页面)之外,则两者都可以正常工作:

<!DOCTYPE html 
     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html 
    xml:lang="pt" 
        lang="pt"
       xmlns="http://www.w3.org/1999/xhtml" 
     xmlns:f="http://java.sun.com/jsf/core"
     xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
     xmlns:p="http://primefaces.prime.com.tr/ui">

    <h:head id="head">
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Item de Texto</title>
    </h:head>
    <h:body id="body">          
        <f:view contentType="text/html"> 
            <h:form id="componentes">  
                <h:panelGrid columns="3">
                    <h:panelGroup>              
                        <h:outputText 
                              escape = "false" 
                               value = "#{editableHTMLText.value}" 
                            rendered = "#{!editableHTMLText.editing}"/>
                        <p:editor 
                            widgetVar = "editor" 
                                value = "#{editableHTMLText.value}" 
                             rendered = "#{editableHTMLText.editing}"/>
                    </h:panelGroup>

                                    <!-- ACTION IS CALLED -->                         
                    <h:commandButton 
                                action = "#{editableHTMLText.toogleEditing}" 
                                 value = "#{editableHTMLText.editing?'Back':'Edit'}" 
                                update = "componentes"/>

                                    <!-- ACTION IS CALLED -->
                    <p:commandButton 
                                action = "#{editableHTMLText.toogleEditing}" 
                                 value = "#{editableHTMLText.editing?'Back':'Edit'}" 
                                update = "componentes"/>
                </h:panelGrid>
            </h:form>                    
        </f:view>
    </h:body>
</html>

这是 bean 代码:

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;


@ManagedBean
@SessionScoped
public class EditableHTMLText implements Serializable{

    /**
     * 
     */
    private static final long   serialVersionUID    = 8439126615761864409L;

    private String              value               = "Test<br>of<br>HTML<br>text<br><b>ITEM</b><br>";
    private boolean             editing             = false;


    public void toogleEditing(){

        this.setEditing(!this.isEditing());
        System.out.println("Editing State: " + this.editing);
    }


    public String getValue(){

        return value;
    }


    public void setValue(String value){

        this.value = value;
    }


    public boolean isEditing(){

        return editing;
    }


    public void setEditing(boolean editing){

        this.editing = editing;
    }

}

有什么建议吗?

In the code bellow the jsf html commandButton action is called perfectly.
But primefaces commandButton action is not called.

<ui:component          
              xmlns="http://www.w3.org/1999/xhtml" 
            xmlns:f="http://java.sun.com/jsf/core"
            xmlns:h="http://java.sun.com/jsf/html"
           xmlns:ui="http://java.sun.com/jsf/facelets"
            xmlns:p="http://primefaces.prime.com.tr/ui"
    xmlns:composite="http://java.sun.com/jsf/composite">

    <composite:interface>
        <composite:attribute 
            name="managedBean"          
            type="java.lang.Object"
            required="true">                    
        </composite:attribute>
    </composite:interface>

    <composite:implementation>
        <f:view contentType="text/html"> 
            <h:form id="componentes">  
                <h:panelGrid columns="3">
                    <h:panelGroup>              
                        <h:outputText 
                              escape = "false" 
                               value = "#{cc.attrs.managedBean['value']}"       
                            rendered = "#{!cc.attrs.managedBean['editing']}"/> 
                        <p:editor 
                            widgetVar = "editor" 
                                value = "#{cc.attrs.managedBean.value}" 
                             rendered = "#{cc.attrs.managedBean.editing}"/>
                    </h:panelGroup>
                    <!-- ACTION IS CALLED -->                                 
                    <h:commandButton 
                                action = "#{cc.attrs.managedBean.toogleEditing}" 
                                 value = "#{cc.attrs.managedBean.editing?'Back':'Edit'}" 
                                update = "componentes"/>

                                    <!-- ACTION IS NOT CALLED -->           
                    <p:commandButton 
                                action = "#{cc.attrs.managedBean.toogleEditing}" 
                                 value = "#{cc.attrs.managedBean.editing?'Back':'Edit'}" 
                                update = "componentes"/>
                </h:panelGrid>
            </h:form>                    
        </f:view>
    </composite:implementation>
</ui:component>

If place the same code is outside a composite (a normal xhtml page), both work fine:

<!DOCTYPE html 
     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html 
    xml:lang="pt" 
        lang="pt"
       xmlns="http://www.w3.org/1999/xhtml" 
     xmlns:f="http://java.sun.com/jsf/core"
     xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
     xmlns:p="http://primefaces.prime.com.tr/ui">

    <h:head id="head">
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Item de Texto</title>
    </h:head>
    <h:body id="body">          
        <f:view contentType="text/html"> 
            <h:form id="componentes">  
                <h:panelGrid columns="3">
                    <h:panelGroup>              
                        <h:outputText 
                              escape = "false" 
                               value = "#{editableHTMLText.value}" 
                            rendered = "#{!editableHTMLText.editing}"/>
                        <p:editor 
                            widgetVar = "editor" 
                                value = "#{editableHTMLText.value}" 
                             rendered = "#{editableHTMLText.editing}"/>
                    </h:panelGroup>

                                    <!-- ACTION IS CALLED -->                         
                    <h:commandButton 
                                action = "#{editableHTMLText.toogleEditing}" 
                                 value = "#{editableHTMLText.editing?'Back':'Edit'}" 
                                update = "componentes"/>

                                    <!-- ACTION IS CALLED -->
                    <p:commandButton 
                                action = "#{editableHTMLText.toogleEditing}" 
                                 value = "#{editableHTMLText.editing?'Back':'Edit'}" 
                                update = "componentes"/>
                </h:panelGrid>
            </h:form>                    
        </f:view>
    </h:body>
</html>

This is the bean code:

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;


@ManagedBean
@SessionScoped
public class EditableHTMLText implements Serializable{

    /**
     * 
     */
    private static final long   serialVersionUID    = 8439126615761864409L;

    private String              value               = "Test<br>of<br>HTML<br>text<br><b>ITEM</b><br>";
    private boolean             editing             = false;


    public void toogleEditing(){

        this.setEditing(!this.isEditing());
        System.out.println("Editing State: " + this.editing);
    }


    public String getValue(){

        return value;
    }


    public void setValue(String value){

        this.value = value;
    }


    public boolean isEditing(){

        return editing;
    }


    public void setEditing(boolean editing){

        this.editing = editing;
    }

}

Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

月亮坠入山谷 2024-12-18 09:27:39

今天我在使用 PrimeFaces 5.1 时遇到了同样的问题。就我而言,我没有嵌套表单,并且我已经使用我想要处理的表单元素在 p:commandButton 上设置了 process 属性。然而这还没有奏效。

“解决方案”是将 @this 添加到要处理的组件列表中,如下所示:

@this (通常不需要,因为按钮本身不需要处理/验证)我发现没有办法让这些在组合内部工作:

  • 带有嵌套的
  • 以及关联的

通过调试应用程序,我看到验证和更新模型阶段已正确执行,但在调用应用程序阶段不存在排队事件,因此未执行任何操作。实际上,我可以在 actionactionListener 属性值中指定任何我喜欢的内容,而不会引起 PrimeFaces 或 JSF 的抱怨以任何方式。

相反,这些确实可以正常工作,但是您没有进行部分处理,因此它们可能不是一个可行的解决方案:

  • 嵌套

这一定是 PrimeFaces 的错误。

Today I hit this exact same problem with PrimeFaces 5.1. In my case I had no nested forms and I was already setting the process attribute on the p:commandButton with the form elements I wanted to be processed. However this didn't work yet.

The "solution" was to add @this to the list of components to process, like this:

<p:commandButton process="myFormField1 myFormField2 @this">

Without @this (which is not usually needed, since the button itself shouldn't need to be processed/validated) I found no way to make any of these to work inside a composite:

  • <p:commandButton action="#{bean.myAction}"...>
  • <p:commandButton type="button"> with nested <p:ajax event="click" action="#{bean.myAction}"...>
  • <p:commandButton type="button" onclick="myAction()"> with associated <p:remoteCommand name="myAction" action="#{bean.myAction}">

By debugging the application, I saw that the validation and update model phases were correctly executed, but then in the invoke application phase no queued event was present and hence no action was performed. Actually, I could specify anything I liked inside the action and actionListener attribute values of <p:commandButton> without having either PrimeFaces or JSF complain in any way.

These, instead, do work as they should, but you don't have partial processing in place, so they may not be a viable solution:

  • <p:commandButton action="#{bean.myAction}" ajax="false"...>
  • <p:commandButton type="button"...> with nested <f:ajax event="click" action="#{bean.myAction}"...>

It must be a PrimeFaces bug.

夜未央樱花落 2024-12-18 09:27:39

当你使用复合组件时,它是否已经放在ah:form标签中了?当您有嵌套表单时,不会触发命令按钮操作。

另一个问题可能是您正在尝试的 ajax 部分。 Primefaces 按钮具有更新属性,但标准 JSF 按钮没有该属性。它将始终对页面进行完全刷新(除非嵌套在其中或在其中使用 f:ajax 标记)

When you used the composite component, was it already placed in a h:form tag? When you have nested forms, command button action isn't triggered.

Another issue can be the ajax parts that you are trying. Primefaces button has the update attribute, but the standard JSF one does not have that. It will do always a complete refresh of the page (except when nested in or f:ajax tag is used inside it)

薄荷→糖丶微凉 2024-12-18 09:27:39

您可以尝试在 p:commandButton 中插入 ajax="false" 属性。

You can try to insert ajax="false" attribute in p:commandButton.

蓬勃野心 2024-12-18 09:27:39

我也遇到了非触发命令按钮的问题。就我而言,ajax 和非 ajax 请求不起作用。
1.如上所述-请务必删除表单中的所有表单。复合使用很容易完成。
2. 如果您有多个按钮,请尝试使用“process”标志。
对我的情况有帮助。

<p:commandButton id="submitButton" value="Submit" type="submit" 
    actionListener="#{bean.save}"
    update="message"
    process="txtComment, @this"
    icon="ui-icon-disk"/>

process="txtComment, @this" 执行id为txtComment的inputText的setter方法和commandButton方法。

I had also problems with non-triggering commandButtons. In my case ajax and non-ajax reqeuests didn't work.
1. as described above - be sure to delete all form's in form's. easy done with composite usage.
2. if you have several buttons, try to use the flag "process".
Helped in my case.

<p:commandButton id="submitButton" value="Submit" type="submit" 
    actionListener="#{bean.save}"
    update="message"
    process="txtComment, @this"
    icon="ui-icon-disk"/>

process="txtComment, @this" executes the setter method of inputText with id txtComment and the commandButton method.

无边思念无边月 2024-12-18 09:27:39

可能您的页面中有一些元素,com REQUIRED =“TRUE”是冲突的

probably you have some elements in your page, com REQUIRED="TRUE" is conflicting

﹏半生如梦愿梦如真 2024-12-18 09:27:39

我也遇到了这个问题并测试了您的代码,似乎 primefaces 无法在同一个“xhtml”中警告您验证错误,但在其他 panelGrid 中,您可能需要一个父 panelGrid 来正确封装所有表单的网格。

如果您完全填写了整个表单,您将看到您的 primefaces commandButton 操作被调用,否则它会默默地“消化”您可能遇到的验证错误。

I also hit this problem and tested out your codes, it seems that primefaces is unable to warn you validation errors in the same "xhtml" but in other panelGrids, you may need a parent panelGrid to properly encapsulate all your form's grids.

If you fill up your entire form completely, you will see that your primefaces commandButton action is called upon, otherwise it would silently "digest" the validation errors you may have.

不乱于心 2024-12-18 09:27:39

为了完整起见,添加到上述答案中。

上述答案中未涵盖的问题之一是 composite:interface 中缺少 Targets 属性

来自 JSF 的文档

targets 属性: 如果此元素具有方法签名
属性,targets 属性的值必须解释为
空格(不是制表符)分隔的客户端 ID 列表(相对于顶部
级组件)内的组件
<复合:实现>部分。空间被用作
用于与 IDREFS 和 NMTOKENS 数据类型兼容的分隔符
来自 XML 模式。列表中的每个条目必须被解释为
来自 MethodExpression 的内部组件的 id
使用页面中必须应用复合组件标签。如果这个
元素有一个方法签名属性,但没有目标属性,
name 属性的值用作中的单个条目
列表。如果 name 属性的值不是特殊值之一
名称属性、目标(或
它的派生值)不需要对应于内部的 id
组件。

<cc:interface>
    <cc:attribute name="value" />
    <cc:attribute name="action" targets="buttonId" />
    <cc:attribute name="actionListener" targets="buttonId" />
</cc:interface>
<cc:implementation>
    <p:commandButton id="buttonId" value="#{cc.attrs.value}" />
</cc:implementation>

@source:https://stackoverflow.com/a/19680483/1850844

To add to the above answers, for completeness.

One of the issue not covered in the above answers is the missing Targets attribute in composite:interface

From the docs of JSF

targets attribute: If this element has a method-signature
attribute, the value of the targets attribute must be interpreted as a
space (not tab) separated list of client ids (relative to the top
level component) of components within the
<composite:implementation> section. Space is used as the
delimiter for compatibility with the IDREFS and NMTOKENS data types
from the XML Schema. Each entry in the list must be interpreted as the
id of an inner component to which the MethodExpression from the
composite component tag in the using page must be applied. If this
element has a method-signature attribute, but no targets attribute,
the value of the name attribute is used as the single entry in the
list. If the value of the name attribute is not one of the special
values listed in the description of the name attribute, targets (or
its derived value) need not correspond to the id of an inner
component.

<cc:interface>
    <cc:attribute name="value" />
    <cc:attribute name="action" targets="buttonId" />
    <cc:attribute name="actionListener" targets="buttonId" />
</cc:interface>
<cc:implementation>
    <p:commandButton id="buttonId" value="#{cc.attrs.value}" />
</cc:implementation>

@source: https://stackoverflow.com/a/19680483/1850844

〃温暖了心ぐ 2024-12-18 09:27:39

我在您的主页中找到了解决此问题的方法

<composite:implementation>
 <p:commandButton onclick="JS_call_to<p:remoteCommand>" />
</composite:implementation>

我已经用它从复合组件到我的主页进行了 Gmap 调用

I Found a workaround for this Problem

<composite:implementation>
 <p:commandButton onclick="JS_call_to<p:remoteCommand>" />
</composite:implementation>

Inside your mainpage define with
<p:remoteCommand action="managedBean.call_function()" update="..." />

I have made a Gmap Call with this from a Composite-Component to my Mainpage

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文