代码之家  ›  专栏  ›  技术社区  ›  Marcin Tomiak

如何将工作命令链接作为子链接添加到组件

  •  0
  • Marcin Tomiak  · 技术社区  · 11 年前

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

    @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)

    1 回复  |  直到 11 年前
        1
  •  0
  •   Marcin Tomiak    11 年前

    我终于把这件事做好了。我所讨论的JSF组件应该有三个类:组件、呈现器和组件处理程序。

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

    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将出现在组件树中。

    在渲染器的decode()方法中,actionListener应设置为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);
        }
    
    }   
    

    现在一切都在工作,动作被调用了!