2015-01-12 2 views
2

Когда я направить АЯКС события из Составных компонента с помощью <cc:clientBehavior name="chartUpdated" event="change" targets="chartdata"/> я ловлю его на Facelet страницы с помощью <f:ajax event="chartUpdated" listener="#{bean.updateListener}">. И В бэк-бобов Я регистрирую событие типа AjaxBehaviorEvent.Как расширить AjaxBehaviorEvent, отправленный с @FacesComponent?

public void updateListener(AjaxBehaviorEvent event){ 
     ... 
} 

Я undertand, что я могу продлить AjaxBehaviorEvent и передать в него объект, который был изменен. For example, Primefaces's Scheduler uses this approach:

<p:ajax event="eventMove" listener="#{scheduleView.onEventMove}" update="messages" /> 

И поддержка боб:

public void onEventMove(ScheduleEntryMoveEvent event) { 
     FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Event moved", "Day delta:" + event.getDayDelta() + ", Minute delta:" + event.getMinuteDelta()); 

     addMessage(message); 
    } 

Можно ли достичь той же функциональности, используя Составной компонент вместе с @FacesComponent?

Спасибо заранее!

ответ

2

Приятно познакомиться, снова :)

продолжается с предыдущего question:

queueEvent() Override отфильтровать интересные события (изменения от конкретных компонентов) и отложить их Ставить на этапе проверки, чтобы иметь возможность получать конвертируется & валидированные значения:

@FacesComponent("rangeComponent") 
public class RangeComponent extends UIInput implements NamingContainer 
{ 
    private final List<AjaxBehaviorEvent> customEvents = new ArrayList<>(); 
    ... 

    @Override 
    public void queueEvent(FacesEvent event) 
    { 
     FacesContext context = getFacesContext(); 
     if(event instanceof AjaxBehaviorEvent) 
     { 
      Map<String, String> params = context.getExternalContext().getRequestParameterMap(); 
      String eventName = params.get("javax.faces.behavior.event"); 
      Object eventSource = event.getSource(); 

      if("change".equals(eventName) && (from.equals(eventSource) || to.equals(eventSource))) 
      { 
       customEvents.add((AjaxBehaviorEvent) event); 
       return; 
      } 
     } 

     super.queueEvent(event); 
    } 

    @Override 
    public void validate(FacesContext context) 
    { 
     super.validate(context); 

     if(from.isValid() && to.isValid()) 
     { 
      for(AjaxBehaviorEvent event : customEvents) 
      { 
       SelectEvent selectEvent = new SelectEvent(this, event.getBehavior(), this.getValue()); 

       if(event.getPhaseId().equals(PhaseId.APPLY_REQUEST_VALUES)) 
       { 
        selectEvent.setPhaseId(PhaseId.PROCESS_VALIDATIONS); 
       } 
       else 
       { 
        selectEvent.setPhaseId(PhaseId.INVOKE_APPLICATION); 
       } 

       super.queueEvent(selectEvent); 
      } 
     } 
    } 

    ... 
} 

затем добавить конкретный слушатель событий в управляемом фасоли:

@ManagedBean 
@ViewScoped 
public class RangeBean implements Serializable 
{ 
    private static final long serialVersionUID = 1L; 

    private String range = "01/01/2015-31/12/2015"; 

    public void onSelect(SelectEvent event) 
    { 
     Messages.addGlobalInfo("[{0}] selected: [{1}]", event.getComponent().getId(), event.getObject()); 
    } 

    public String getRange() 
    { 
     return range; 
    } 

    public void setRange(String range) 
    { 
     this.range = range; 
    } 
} 
+0

Я тоже :) Спасибо за помощь. Я реализовал ваше решение без применения метода ** validate **, и он работает нормально. Что мне не хватает? – Anatoly

+1

Это зависит от фазы. Если событие запускается в фазе APPLY_REQUEST_VALUES (например, события «change»), вызовы 'component.getValue()' возвращают устаревшее значение. В противном случае нет необходимости откладывать, т. Е. События «valueChange» запускаются в фазе PROCESS_VALIDATIONS. –

+2

Следует отметить, что этот подход тесно связан с PrimeFaces из-за 'Constants'. Если вы планируете использовать компонент для повторного использования во всех библиотеках компонентов, вам лучше удалить импорт из PrimeFaces. – BalusC