3

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

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

    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>调用ComplianceCaseManager类方法。setSelectedComplianceCaseWithRefresh( ComplianceCase selectedComplianceCase )var="coca"

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

调试显示该setSelectedComplianceCaseWithRefresh( ComplianceCase selectedComplianceCase )方法从未被调用。

问:

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

PS:配置是 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 并在 value 上调用 setter,所以我假设ValueExpressions 就足够了。


更新 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。记得setId()在实例化 PrimeFaces 时调用CommandButton

4

2 回答 2

1

一个 actionListener 应该被创建为 a MethodExpressionnot a 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编辑:动态创建命令组件时,您绝对必须设置属性

于 2013-06-27T12:42:44.067 回答
0

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

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

然后只是:

  1. 设置命令按钮 idcomandButton.setId(id);
  2. 添加de ActionListenercommandButon.addActionListener(actionListener);
于 2016-02-11T17:16:04.527 回答