【问题标题】:How to add a working command link as a child to the component如何将工作命令链接作为子组件添加到组件
【发布时间】:2013-10-02 18:32:52
【问题描述】:

我在我的应用程序中实现了以下自定义组件:

@FacesComponent ("org.app.component.hintBubble")
public class TutorialHintBubbleComponent extends UIComponentBase implements Serializable {

private static final long serialVersionUID = -8124906197708898894L;

public static final String COMPONENT_TYPE = "org.app.component.hintBubble";

@Override
public String getFamily() {
    return COMPONENT_TYPE;
}

@Override
public boolean isTransient() {
    return false;
}

@Override
public void encodeBegin(FacesContext context) throws IOException {
    setId("hintBubble");

    TutorialHintBubble value = (TutorialHintBubble) this.getValueExpression("value").getValue(context.getELContext());
    ResponseWriter writer = context.getResponseWriter();
    writer.startElement("div", this);
        writer.writeAttribute("style", value.getCss().getBodyCss(), null);
        writer.writeAttribute("class", "hint-bubble", null);

        if ( value.getPointer().getLocation() != HintBubblePoinerLocation.NONE ) {
            writer.startElement("div", this);
                writer.writeAttribute("style", value.getCss().getPointerCss(), null);
                writer.writeAttribute("class", "hint-bubble-pointer", null);
            writer.endElement("div");

            if ( value.getBorder().getThicknessInPixels() > 0 ) {
                writer.startElement("div", this);
                    writer.writeAttribute("style", value.getCss().getPointerBorderCss(), null);
                    writer.writeAttribute("class", "hint-bubble-pointer-border", null);
                writer.endElement("div");
            }
        }



        writer.startElement("div", this);
            writer.writeAttribute("class", "hint-bubble-inner-html-container", null);
            writer.write(value.getInnerHtml());
        writer.endElement("div");

        if ( value.isShowConfirmButton() ) {
            writer.startElement("div", this);
            writer.writeAttribute("class", "hint-bubble-btn-container", null);

            UICommandLink commandLink = new UICommandLink();
            getChildren().add(commandLink);
            commandLink.setParent(this);

            commandLink.setValue(value.getButtonCaption());
            commandLink.setStyleClass("hint-bubble-btn");
            commandLink.setId("okButton");

            ValueExpression actionListenerExpression = getValueExpression("actionListener");

            if ( actionListenerExpression != null ) {
                commandLink.addActionListener(
                    (ActionListener) actionListenerExpression.getValue(context.getELContext())
                );
            }
        }
    }


@Override
public void encodeEnd(FacesContext context) throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    TutorialHintBubble value = (TutorialHintBubble) this.getValueExpression("value").getValue(context.getELContext());
    if ( value.isShowConfirmButton() ) {
        writer.endElement("div");
    }

    writer.endElement("div");
}

}

如您所见,该组件添加了 UICommandLink 作为子组件。附加到此命令链接的是 ActionListener。 ActionListener 是根据作为参数传递给 HintBubble 组件的表达式进行评估的。调试显示动作侦听器已正确评估并添加到 UICommandLink。

xhtml 中的代码:

<h:form id="tutorialForm">
<a4j:outputPanel id="tutorialContainer" layout="block" >
    <a4j:repeat value="#{tutorialBean.hintBubbles}" var="hintBubble">
        <gg:hintBubble value="#{hintBubble}" actionListener="#{tutorialManager}" />
    </a4j:repeat>
</a4j:outputPanel>
</h:form>

网页上的所有内容都正确呈现,但是当我单击按钮时未执行操作。 (虽然ajax请求是发给服务器的)

我的问题是:

我应该在哪种方法中将 UICommandLink 添加到组件的子组件中才能正常工作? (请注意,UICommandLink 来自 Richfaces,即它是 org.richfaces.component.UICommandLink)

【问题讨论】:

    标签: ajax jsf jsf-2 custom-component


    【解决方案1】:

    我终于设法让这个工作。我提出的 JSF 组件应该具有三个类:Component、Renderer 和 ComponentHandler。

    应将子 UICommandLink 添加到其 ComponentHandler 中的 HintBubbleComponent 在创建的组件的方法中:

    public class HintBubbleHandler extends ComponentHandler {
    
    public HintBubbleHandler(ComponentConfig config) {
        super(config);
    }
    
    @Override
    public void onComponentCreated(FaceletContext ctx, UIComponent c, UIComponent parent) {
        HintBubbleComponent hintBubbleComponent = (HintBubbleComponent) c;
    
        UICommandLink commandLink = new UICommandLink();
        hintBubbleComponent.getChildren().add(commandLink);
        commandLink.setParent(hintBubbleComponent);
        commandLink.setId("okButton");      
    }
    

    }

    因此,当回调访问树以查找执行操作的组件时,UICommandLink 将出现在组件树中。

    actionListener 应该在渲染器的 decode() 方法中设置为 UICommandLink:

    @Override
    public void decode(FacesContext context, UIComponent component) {
        super.decode(context, component);
    
        UICommandLink commandLink = (UICommandLink) component.getChildren().get(0);
    
        MethodExpression actionListener =  ((HintBubbleComponent) component).getActionListener();
    
        if ( actionListener != null ) {
            commandLink.setActionExpression(actionListener);
        }
    
    }   
    

    现在一切都在调用动作!

    【讨论】:

      猜你喜欢
      • 2016-12-16
      • 1970-01-01
      • 2019-12-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多