Как добавить динамический динамик ajax для моей панели?

2 Samolo [2013-08-29 17:15:00]

Я динамически создаю свою панель, и я хочу динамически добавлять ajax close listener, но не работает для меня. Для каждой панели:

    int u = _memosId.get(i);
    Panel panel = (Panel)_application.createComponent(_context, "org.primefaces.component.Panel", "org.primefaces.component.PanelRenderer");

    panel.setId("mymemo_" + String.valueOf(u));
    panel.setHeader(_userNames.get(i));
    panel.setClosable(true);
    panel.setToggleable(true);


    HtmlOutputText memo = new HtmlOutputText();
    memo.setValue(_userMemos.get(i));  
    panel.getChildren().add(memo);


    AjaxBehavior ajaxBehavior =(AjaxBehavior)_context.getApplication().createBehavior(AjaxBehavior.BEHAVIOR_ID);
    ajaxBehavior.addAjaxBehaviorListener(new ClosePanelListener());
    ajaxBehavior.setTransient(true);
    panel.addClientBehavior("close", ajaxBehavior);

    _column1.addWidget(panel.getId());
    getDashboard().getChildren().add(panel);

и слушатель моего класса:

    private static class ClosePanelListener implements AjaxBehaviorListener 
    {

        @Override
        public void processAjaxBehavior(AjaxBehaviorEvent event) throws AbortProcessingException 
        {
         System.out.println("----------->>>>>>>>>>AjaxListener CALLED!!! "); 
        }
    }

Слушатель не вызывается.

ajax jsf primefaces


2 ответа


3 Решение BalusC [2013-08-30 19:10:00]

Ваша конкретная проблема вызвана тем, что следующая строка,

AjaxBehavior ajaxBehavior =(AjaxBehavior)_context.getApplication().createBehavior(AjaxBehavior.BEHAVIOR_ID);

по существу создает <f:ajax>, в то время как этот <p:panel> закрытый прослушиватель действительно поддерживается только <p:ajax>. Вы также можете увидеть его в сгенерированном HTML-выходе; Mojarra.ab() (или любая специальная функция MyFaces в случае использования MyFaces вместо Mojarra) используется вместо PrimeFaces.ab().

Чтобы правильно создать <p:ajax>, вам нужно использовать собственный AjaxBehavior и позволить вашему слушателю простираться от собственного AjaxBehaviorListenerImpl от AjaxBehaviorListenerImpl:

import org.primefaces.component.behavior.ajax.AjaxBehavior;
import org.primefaces.component.behavior.ajax.AjaxBehaviorListenerImpl;
AjaxBehavior ajaxBehavior = new AjaxBehavior();
public static class ClosePanelListener extends AjaxBehaviorListenerImpl

(обратите внимание, что я сменил вложенный класс от private к public, иначе вы можете столкнуться с проблемами видимости с некоторыми EL-объектами)


Не связанное с конкретной проблемой соглашение об использовании именования переменных _application и _context предполагает, что они содержатся как переменные экземпляра класса бэк-компонента. Это очень плохая идея по проектированию и безопасности потоков. Они должны быть получены в локальной области метода и никогда не должны быть назначены в качестве переменных экземпляра.

Кроме того, считали ли вы <ui:repeat> или <c:forEach> для самой цели динамического создания панелей в цикле? Это будет в гораздо более чистом и декларативном коде, чем этот беспорядок.


0 kaos [2013-08-29 17:47:00]

Попробуйте использовать методExpression вместо прямого создания вашего слушателя. В этом случае ClosePanelListener должен быть управляемым компонентом.

 Application application = _context.getApplication();
 ExpressionFactory ef = _context.getApplication().getExpressionFactory();
 MethodExpression me = ef.createMethodExpression(_context.getELContext(),
     "#{closePanelListenerBean.processAjaxBehavior()}", null, new Class[]{AjaxBehaviorEvent.class});

 AjaxBehavior ajaxBehavior = new AjaxBehavior();
 AjaxBehaviorListenerImpl ajaxBehaviorImpl = new AjaxBehaviorListenerImpl(me, me);        
 ajaxBehavior.addAjaxBehaviorListener(ajaxBehaviorImpl);       
 panel.addClientBehavior("close", ajaxBehavior);