带按钮的JSF自定义面板 - 未调用动作
问题描述:
我已经构建了一个自定义组件按钮,但不知何故该动作未被调用。在组件中调试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" />
答
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所做的那样。