2012-08-17 59 views
2

我已经构建了一个自定义组件按钮,但不知何故该动作未被调用。在组件中调试getAction-Method并调用提供的MethodeExpression时,Bean-Method将按预期调用。但由于某种原因,在浏览器中按下按钮时不会调用Expression。带按钮的JSF自定义面板 - 未调用动作

是否需要将某种附加接口传递给嵌入式按钮组件?

任何帮助是非常赞赏,因为我停留在这个问题上一些日子现在

MyClass的:

public class MyClass extends UIPanel implements SystemEventListener 
{ 

private UIForm    form; 
private HtmlCommandButton buttonOk; 

public MyClass() 
{ 
    FacesContext context = getFacesContext(); 
    UIViewRoot root = context.getViewRoot(); 
    root.subscribeToViewEvent(PostAddToViewEvent.class, this); 
} 


@Override 
public void processEvent(SystemEvent event) 
{ 
    this.form = new UIForm(); 
    this.buttonOk = new HtmlCommandButton(); 
    this.buttonOk.setId("okButtonId"); 
    this.buttonOk.setActionExpression(getAction()); 
    this.buttonOk.setValue("OK"); 
    this.form.getChildren().add(this.buttonOk); 
    getChildren().add(this.form); 
} 


private enum PropertyKeys 
{ 
    action, text, titel 
} 


public MethodExpression getAction() 
{ 
    return (MethodExpression) getStateHelper().eval(PropertyKeys.action); 
} 


public void setAction(MethodExpression actionExpression) 
{ 
    getStateHelper().put(PropertyKeys.action, actionExpression); 
} 


public String getText() 
{ 
    return (String) getStateHelper().eval(PropertyKeys.text); 
} 


public void setText(String text) 
{ 
    getStateHelper().put(PropertyKeys.text, text); 
} 


public String getTitel() 
{ 
    return (String) getStateHelper().eval(PropertyKeys.titel); 
} 


public void setTitel(String titel) 
{ 
    getStateHelper().put(PropertyKeys.titel, titel); 
} 


@Override 
public void encodeAll(FacesContext context) throws IOException 
{ 
    ResponseWriter writer = context.getResponseWriter(); 
    writer.startElement(HTML.DIV_ELEM, this); 
    writer.writeText(getText(), null); 
    this.form.encodeAll(context); 
    writer.endElement(HTML.DIV_ELEM); 
} 


@Override 
public void encodeChildren(FacesContext context) throws IOException 
{ 

} 


@Override 
public boolean isListenerForSource(Object source) 
{ 
    return (source instanceof MyClass); 
} 

}

MyClassHandler:

public class MyClassHandler extends ComponentHandler 
{ 

public MyClassHandler(ComponentConfig config) 
{ 
    super(config); 
} 


@SuppressWarnings("rawtypes") 
@Override 
protected MetaRuleset createMetaRuleset(Class type) 
{ 
    return super.createMetaRuleset(type).addRule(new MethodRule("action", String.class, new Class[] { ActionEvent.class })); 
} 

}

MyView的方法:

... 
public String myMethod() 
{ 
    System.err.println("myMethod"); 
    return "/some/path/yadayada.xhtml"; 
} 
... 

MyView.xhtml

<myTag action="#{myView.myMethod}" id="id1" titel="bla" text="bleh" /> 

回答

1

Exdending UICommand就够了,因为你只需要执行一个动作。

您必须通过标签属性提供两个额外的MethodExpressions,并在decode-method内您可以检查哪个按钮已被按下,并将特定的MethodExpression重定向到由UICommand提供的标准操作。这样,您不必担心传统界面的ActionSource,或者如何广播事件。

public void decode(FacesContext contex) 
{ 
    Map<String,String> map = context.getExternalContext.getRequestParameterMap(); 
    // your rendered buttons need a name you check for 
    final boolean okPressed = map.containsKey(getClientId + ":ok"); 
    final boolean cancelPressed = map.containsKey(getClientId + ":cancel"); 
    if(okPressed || cancelPressed) 
    { 
     MethodExpression exp = null; 
     if(okPressed) 
     { 
      exp = getActionOk(); 
     } 
     else 
     { 
      exp = getActionCancel(); 
     } 
     // redirect to standard action 
     setActionExpression(exp); 
     queueEvent(new ActionEvent(this)); 
    } 
} 

为了利用这需要两个属性(actionOk和actionCancel)的使用方法表达式(setter和getter)。这些必须由ComponentHandler进行配置,就像您对action-attribute所做的那样。