2013-06-27 3 views
3

У нас есть требование разрешить пользователям настраивать порядок столбцов во всех типах данных, включая столбцы с кнопками действий на них, здесь p:commandButton s.JSF/PrimeFaces: программный <f: setPropertyActionListener> on <p: commandButton> not firing

Следовательно, мы используем привязку для всех наших столбцов, которые мы должны создавать вручную. Для всех столбцов, которые отображают только некоторые строки, логические значения, даты и числа работают нормально, однако проблемы возникают при добавлении p:commandButton s к столбцам, у которых есть один или несколько <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) метод с текущим объектом DataTable в (как определено var="coca") перед показом диалога.

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

Debugging показывает метод setSelectedComplianceCaseWithRefresh(ComplianceCase selectedComplianceCase) никогда не вызывается.

Q:

Что случилось? Как вы это исправите?

PS: конфигурация является PrimeFaces 3.4.2, 2.1.22 Mojarra, GlassFish 3.1.2.2, Java 7


Update 1:

Вот р: 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 сделан так, что на цели сеттер называется и по значению называется сеттер, так что я d предположим, что ValueExpression s будет достаточным.


Update 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)); 

Ничто не называется.


Update 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.

+1

ли вы установить 'id' атрибут? – kolossus

+0

OMG. : -O Это действительно решило! Пожалуйста, разместите его как ответ. :-) – Kawu

+0

Он уже там :) – kolossus

ответ

1

ActionListener должен быть создан как MethodExpression не ValueExpression:

  1. Я предполагаю, что factory instanceOf ExpressionFactory. Используйте createMethodExpression factory

    MethodExpression targetExpression = factory.createMethodExpression(elContext, "#{complianceCaseManager.selectedComplianceCaseWithRefresh(coca)}",null,new Class[]{ComplianceCase.class}); 
    
  2. Добавление слушателя к компоненту:

    button.addActionListener(new MethodExpressionActionListener(targetExpression)); 
    
  3. Не полностью связан с текущей проблемой, вы также опустить атрибут компонента id. Чтобы обезопасить себя, добавить

    button.setId("theButton"); 
    

    EDIT: Вы абсолютно должны установить атрибут id при динамическом создании командных компонентов

+0

Не может работать. Согласно https://community.jboss.org/message/616594#616594 и Java-документам подпись для конструктора 'SetPropertyActionListenerImpl' является' com.sun.faces.taglib.jsf_core.SetPropertyActionListenerImpl.SetPropertyActionListenerImpl (TargetExpression target, ValueExpression value) '. 'MethodExpression' не наследуется от' ValueExpression', а только 'Expression'. – Kawu

+0

@Kawu, мой недосмотр. См. Мое обновление. – kolossus

+0

Это может быть крайним средством для использования прямых вызовов метода EL 2.2. Тем не менее, мне было интересно, как перевести «старую школу» JSF 1.2 ' на программные варианты. Посмотрите мое обновление, чтобы увидеть '' в простой JSF. – Kawu

0

Я использовал, чтобы решить эту проблему с помощью лямбда-выражения:

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

, а затем только:

  1. набор де CommandButton ID comandButton.setId(id);
  2. добавить де ActionListener commandButon.addActionListener(actionListener);