JSF HtmlCommandButton以编程方式 - 如果关闭ajax,则不调用Bean方法

时间:2017-12-01 08:45:44

标签: ajax jsf-2 commandbutton

我尝试以编程方式创建HtmlCommandButton,按照此处的示例

http://javaevangelist.blogspot.ch/2013/01/jsf-21-tip-of-day-programmatically.html

如果我添加ajax行为,一切正常(即调用actionListener),如果关闭ajax,它就不起作用。

支持bean:

@Named
@RequestScoped
public class CommandBean implements Serializable {

   public String generateUUID() {
        return java.util.UUID.randomUUID().toString();
    }
}

解决方案1(使用ajax)

private HtmlCommandButton createCommandButtonWithAjax(final FacesContext context,
        final String methodExpression, final String value) {

    Application application = context.getApplication();
    Class<?>[] clazz = new Class<?>[]{};
    HtmlCommandButton htmlCommandButton =
            (HtmlCommandButton) application.createComponent(HtmlCommandButton.COMPONENT_TYPE);
    htmlCommandButton.setValue(value);

    AjaxBehavior ajaxBehavior = (AjaxBehavior) FacesContext.getCurrentInstance().getApplication().createBehavior(AjaxBehavior.BEHAVIOR_ID);
    ((UIComponentBase)htmlCommandButton).addClientBehavior("click", ajaxBehavior);

MethodExpression actionListener = application.getExpressionFactory().createMethodExpression(FacesContext.getCurrentInstance().getELContext(), action, String.class, clazz);
button.addActionListener(new MethodExpressionActionListener(actionListener));

    return htmlCommandButton;
}

解决方案2(没有ajax)

private HtmlCommandButton createCommandButton(final FacesContext context,
        final String methodExpression, final String value) {
    Application application = context.getApplication();
    Class<?>[] clazz = new Class<?>[]{};
    HtmlCommandButton htmlCommandButton =
            (HtmlCommandButton) application.createComponent(HtmlCommandButton.COMPONENT_TYPE);
    htmlCommandButton.setValue(value);
    htmlCommandButton.setActionExpression(JSFUtils.createMethodExpression(methodExpression, String.class, clazz));
    return htmlCommandButton;
}

致电代码:

createCommandButton(FacesContext.getCurrentInstance(),
                "#{commandBean.generateUUID()}", "Generate UUID");

JSFUtils:

  public static MethodExpression createMethodExpression(String methodExpression,Class<?> expectedReturnType,Class<?>[] expectedParamTypes) {
    FacesContext context = FacesContext.getCurrentInstance();
    return context.getApplication().getExpressionFactory()
            .createMethodExpression(context.getELContext(), methodExpression, expectedReturnType, expectedParamTypes);
  }

解决方案1正在运行,解决方案2没有:bean方法generateUUID()未被调用。我还尝试使用htmlCommandButton.setImmediate(true)排除验证错误。

1 个答案:

答案 0 :(得分:1)

显然,我们需要一个自定义AjaxBehavior,如此处所示: https://forum.primefaces.org/viewtopic.php?f=3&t=5344和这里 How to programmatically add an AjaxBehavior to a UIComponent with primefaces

自定义Ajax:

import java.util.HashMap;
import javax.el.ELContext;
import javax.el.MethodExpression;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.BehaviorEvent;

public class MyAjaxBehavior extends AjaxBehavior{


  @Override
  public Object saveState(FacesContext context) {
    HashMap<String, Object> map;
    map = new HashMap<String, Object>();
    map.put( "update", getUpdate() );
    map.put( "process", getProcess() );
    map.put( "oncomplete", getOncomplete() );
    map.put( "onerror", getOnerror() );
    map.put( "onsuccess", getOnsuccess() );
    map.put( "onstart", getOnstart() );
    map.put( "listener", getListener() );

    if (initialStateMarked()) return null;
    return UIComponentBase.saveAttachedState(context, map);

  }

  @SuppressWarnings("unchecked")
  @Override
  public void restoreState(FacesContext context, Object state) {
    if (state != null){
      HashMap<String, Object> map;
      map = (HashMap<String, Object>) UIComponentBase.restoreAttachedState(context, state);

      setUpdate( (String) map.get( "update" ));
      setProcess( (String) map.get( "process"));
      setOncomplete( (String) map.get( "oncomplete" ));
      setOnerror( (String) map.get( "onerror" ));
      setOnsuccess( (String) map.get( "onsuccess" ));
      setOnstart( (String) map.get( "onstart" ));
      setListener( (MethodExpression) map.get( "listener" ));
    }

  }

  @Override
  public void broadcast(BehaviorEvent event) throws AbortProcessingException {
    ELContext eLContext = FacesContext.getCurrentInstance().getELContext();

//Backward compatible implementation of listener invocation
    if(getListener() != null) {
      try {
        getListener().invoke(eLContext, new Object[]{event});
      } catch(IllegalArgumentException exception) {
        getListener().invoke(eLContext, new Object[0]);
      }
    }
  }

}

创建按钮

    private HtmlCommandButton createCommandButtonWithAjax(final FacesContext context,
        final String methodExpression, final String value) {

    Application application = context.getApplication();
    Class<?>[] clazz = new Class<?>[]{};
    HtmlCommandButton htmlCommandButton =
            (HtmlCommandButton) application.createComponent(HtmlCommandButton.COMPONENT_TYPE);
    htmlCommandButton.setValue(value);

    addPrimefacesAjaxSupport(htmlCommandButton,"click", methodExpression);

    return htmlCommandButton;
}

添加AjaxBehavior

  private AjaxBehavior addPrimefacesAjaxSupport(UIComponentBase comp, String event, String actionListener){

    MyAjaxBehavior ajaxBehavior = new MyAjaxBehavior();
    ajaxBehavior.setListener( JSFUtils.createMethodExpression(actionListener, void.class,new Class[]{ ActionEvent.class}) );
    ajaxBehavior.setProcess( "@this" );
    comp.addClientBehavior( event, ajaxBehavior );

    return ajaxBehavior;
  }