2

カスタム コンポーネント ボタンを作成しましたが、どういうわけかアクションが呼び出されません。コンポーネント内で getAction-Method をデバッグし、提供された MethodeExpression を呼び出すと、Bean-Method が期待どおりに呼び出されます。しかし、何らかの理由で、ブラウザでボタンを押したときに Expression が呼び出されません。

アクションを埋め込みボタンコンポーネントに渡すために必要な追加のインターフェイスはありますか?

この問題で数日間立ち往生しているので、どんな助けも大歓迎です

私のクラス:

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" />
4

1 に答える 1

1

実行するアクションは 1 つだけなので、UICommand を拡張するだけで十分です。

tag-attributes を介して 2 つの追加の MethodExpression を提供する必要があり、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));
    }
}

これを利用するには、メソッド式 (setter と getter) を使用する 2 つの属性 (actionOk と actionCancel) が必要です。これらは、action-attribute で行ったように、ComponentHandler によって構成する必要があります。

于 2012-08-22T06:42:05.990 に答える