繁体   English   中英

JSF / PrimeFaces:程序化 <f:setPropertyActionListener> 上 <p:commandButton> 不开火

[英]JSF/PrimeFaces: programmatic <f:setPropertyActionListener> on <p:commandButton> not firing

我们要求允许用户在所有数据表中配置列的顺序,包括在其上有操作按钮的列,这里是p:commandButton

因此,我们对所有列都使用绑定,我们必须手动实例化。 对于只显示一些字符串,布尔值,日期和数字的所有列都可以正常工作,但是当将p:commandButton添加到对它们有一个或多个<f:setPropertyActionListener>的列时会出现问题。

    ELContext elContext = FacesContext.getCurrentInstance().getELContext();
    ExpressionFactory factory = FacesContext.getCurrentInstance().getApplication().getExpressionFactory();

    CommandButton button = new CommandButton();
    button.setIcon( "ui-icon ui-icon-pencil" );
    button.setProcess( "@this" );
    button.setUpdate( ":compliance-case-dialog :compliance-case-form:data" );
    button.setOncomplete( "complianceCaseDialog.show();" );

    ValueExpression targetExpression = factory.createValueExpression( elContext, "#{complianceCaseManager.selectedComplianceCaseWithRefresh}", ComplianceCase.class );
    ValueExpression valueExpression = factory.createValueExpression( elContext, "#{coca}", ComplianceCase.class );

    button.addActionListener( new SetPropertyActionListenerImpl( targetExpression, valueExpression ) );

    column.getChildren().add( button ); // add to Column instance

此按钮“正确”显示<p:dialog> ,但在显示<p:dialog> ,应使用数据表的当前实体(由var="coca"定义setSelectedComplianceCaseWithRefresh( ComplianceCase selectedComplianceCase )调用ComplianceCaseManager类的setSelectedComplianceCaseWithRefresh( ComplianceCase selectedComplianceCase )方法。

<p:dataTable id="data"
             widgetVar="resultTable"
             value="#{complianceCaseManager.complianceCases}"
             var="coca"
             ...>
</p:dataTable>

调试显示从不调用setSelectedComplianceCaseWithRefresh( ComplianceCase selectedComplianceCase )方法。

问:

怎么了? 你是如何解决这个问题的?

PS:config是PrimeFaces 3.4.2,Mojarra 2.1.22,GlassFish 3.1.2.2,Java 7


更新1:

这是p:commandButton我想翻译成程序化的:

<p:commandButton icon="ui-icon ui-icon-pencil"
                 title="#{msg['complianceCaseManager.data.edit.button.hint']}"
                 process="@this"
                 update=":compliance-case-dialog :compliance-case-form:data"
                 oncomplete="complianceCaseDialog.show();">
    <p:resetInput target=":unlocked-form" />
    <f:setPropertyActionListener target="#{complianceCaseManager.selectedComplianceCaseWithRefresh}" value="#{coca}" />
    <f:setPropertyActionListener target="#{complianceCaseManager.mode}" value="EDIT" />
</p:commandButton>

这条线

    <f:setPropertyActionListener target="#{complianceCaseManager.selectedComplianceCaseWithRefresh}" value="#{coca}" />

是我必须上班的人。

kolossus创建MethodExpressionActionListener的解决方案对我的代码不起作用:

    String targetExpressionString = "#{complianceCaseManager.selectedComplianceCaseWithRefresh}";
    String valueExpressionString = "#{coca}";

    MethodExpression targetMethodExpression = factory.createMethodExpression( elContext, targetExpressionString, null, new Class<?>[]{ ComplianceCase.class } );
    MethodExpression valueMethodExpression = factory.createMethodExpression( elContext, valueExpressionString, ComplianceCase.class, new Class<?>[0] );

    button.addActionListener( new MethodExpressionActionListener( targetMethodExpression, valueMethodExpression ) );

AFAIK是这样的,在目标上调用setter并且在调用setter的值上,所以我假设ValueExpression是足够的。


更新2:

尝试通过EL 2.2方法调用设置当前实体也不起作用。

码:

    String methodExpressionString = "#" + "{complianceCaseManager.selectedComplianceCaseWithRefresh(coca)}";
    MethodExpression methodExpression = factory.createMethodExpression( elContext, methodExpressionString, null, new Class<?>[]{ ComplianceCase.class } );

    button.addActionListener( new MethodExpressionActionListener( methodExpression ) );

什么都没有。


更新3:

这是正确的<:setPropertyActionListener>代码:

    // traditional <f:setPropertyActionListener target="#{complianceCaseManager.selectedComplianceCaseWithRefresh}" value="#{coca}" />
    ValueExpression targetExpression = factory.createValueExpression( elContext, "#{complianceCaseManager.selectedComplianceCaseWithRefresh}", ComplianceCase.class );
    ValueExpression valueExpression = factory.createValueExpression( elContext, "#{coca}", ComplianceCase.class );

    button.addActionListener( new SetPropertyActionListenerImpl( targetExpression, valueExpression ) );

非常感谢kolossus。 记得在实例化PrimeFaces CommandButton时调用setId()

应该将actionListener创建为MethodExpression而不是ValueExpression

  1. 我假设factory instanceOf ExpressionFactory 使用createMethodExpression工厂

     MethodExpression targetExpression = factory.createMethodExpression( elContext, "#{complianceCaseManager.selectedComplianceCaseWithRefresh(coca)}",null,new Class[]{ComplianceCase.class} ); 
  2. 将侦听器添加到组件:

     button.addActionListener( new MethodExpressionActionListener(targetExpression)); 
  3. 与当前问题不完全相关,您还省略了组件的id属性。 为了安全起见,请添加

     button.setId("theButton"); 

    编辑:您必须在动态创建命令组件时设置id属性

我曾经使用lambda表达式来解决它:

private final ActionListener actionListener = (ActionEvent event) -> {
            //code to execute
        };

然后只是:

  1. set de CommandButton id comandButton.setId(id);
  2. add de ActionListener commandButon.addActionListener(actionListener);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM