2014-04-30 5 views
5

Ich habe Probleme mit einer benutzerdefinierten Komponente, die ich schreibe, dass es keine verschachtelten Steuerelemente rendern wird. Die Komponente ist eine einfache Layoutsteuerung, die sehr lose von dem ApplicationLayout-Steuerelement in der Erweiterungsbibliothek angepasst wird. Der XPage Code sieht wie folgt aus:Benutzerdefinierte Komponente zeigt verschachtelte Komponenten nicht

<px:exampleControl id="exampleControl1">  
    <xp:span styleClass="mySpan">Inner Text</xp:span> 
</px:exampleControl> 

Die exampleControl machen wird gut, aber die verschachtelte Spanne nicht. Mein Grund Renderer-Code ist:

public class ExampleRenderer extends Renderer { 

@Override 
    public void encodeBegin(FacesContext context, UIComponent component) 
    throws IOException { 

    ResponseWriter writer = context.getResponseWriter(); 
    writer.startElement("div", component); 
    writer.writeAttribute("class", "custom-banner", null); 
    writer.endElement("div"); 
    writer.startElement("div", component); 
    writer.writeAttribute("class", "main-body", null);  

    } 

@Override 
public boolean getRendersChildren() { 
    return true; 
} 

@Override 
public void encodeChildren(FacesContext context, UIComponent component) { 
    try { 
     super.encodeChildren(context, component);  
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

    @Override 
    public void encodeEnd(FacesContext context, UIComponent component) 
    throws IOException { 
    ResponseWriter writer = context.getResponseWriter(); 
    writer.endElement("div"); 
    writer.startElement("div", component); 
    writer.writeAttribute("class", "custom-footer", null);  
    writer.endElement("div"); 
    } 
} 

Ich habe sogar eine bestimmte Render-Funktion entlehnt aus der Extension Library Renderer (die Utility-Funktionen in AbstractApplicationLayoutRenderer.java) aber component.getChildCount() zu verwenden, versucht immer 0 zurück

Warum also nicht die verschachtelten Steuerelemente Rendering und was fehlt mir?

+2

Haben Sie Renderer.encodeChildren überprüft? AFAIK es tut nichts - deshalb musst du es überschreiben, damit der Aufruf von "super" nichts macht. Zumindest müssen Sie rendernChildren [auf true] setzen (http://docs.oracle.com/cd/E17802_01/j2ee/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/render/Renderer.html#encodeChildren % 28javax.faces.context.FacesContext,% 20javax.faces.component.UIComponent% 29) – stwissel

Antwort

7

Ich endlich herausgefunden. Der Renderer-Code war ein bisschen Ablenkungsmanöver, weil Renderer.encodeChildren, wie Stephan (stwissel) kommentierte, nichts tut. Wenn Sie sich die Quelle mehrerer ExtLib-Komponenten ansehen, wird sie von keiner von ihnen verwendet.

Die Änderung, die ich vorgenommen habe, war die Erweiterung Klasse. Nach dem Lesen von Keith Stricklands Blog (http://www.keithstric.com/A55BAC/keithstric.nsf/default.xsp?documentId=82770C11FA7B9B21852579C100581766) und dem Überprüfen von com.ibm.xsp.extlib.component.layout.UIVarPublisherBase habe ich die FacesComponent-Schnittstelle implementiert. Insbesondere wollte ich die buildContents-Methode aufrufen, die den FacesComponentBuilder aufruft. Die JavaDoc für FacesComponent hat dies über FacesComponent zu sagen:

buildContents Bauen Sie die Komponente Kinder und Facetten, die Standardimplementierung ist in der Regel: builder.buildAll (Kontext, dies, true); // includeFacets = true

Meine Erweiterungsklasse endete wie folgt aussehen:

package com.example.component; 

import javax.faces.FacesException; 
import javax.faces.component.UIComponentBase; 
import javax.faces.context.FacesContext; 

import com.ibm.xsp.component.FacesComponent; 
import com.ibm.xsp.page.FacesComponentBuilder; 

public class CustomLayout extends UIComponentBase implements FacesComponent { 

public CustomLayout(){ 
    super(); 
    setRendererType("com.example.applicationlayout"); 
} 

@Override 
public String getFamily() { 
    return "com.example.applicationlayout"; 
} 

public void buildContents(FacesContext context, FacesComponentBuilder builder) 
     throws FacesException {  
    builder.buildAll(context, this, true); 
} 

public void initAfterContents(FacesContext context) throws FacesException { 

} 

public void initBeforeContents(FacesContext context) throws FacesException  

} 
} 

Es scheint jetzt zu arbeiten, wie ich wollte.

Neben anderen Objekten in der ExtLib (UIWidgetContainer und UIList speziell) haben verschiedene Möglichkeiten zum Rendern ihrer untergeordneten Elemente ohne FacesComponent zu implementieren. Das erfordert wahrscheinlich einen Blogbeitrag.

+2

froh, dass du es herausgefunden hast und dass ich helfen konnte. Ich habe versucht, früher zu antworten, hatte aber Authentifizierungsprobleme. – keithstric