2014-04-30 16 views
5

Mam problemy z komponentem niestandardowym, który piszę, ponieważ nie wyrenderuje żadnych zagnieżdżonych elementów sterujących. Komponent to prosta kontrola układu, bardzo luźno zaadaptowana z formantu ApplicationLayout w bibliotece rozszerzeń. Kod XPage wygląda następująco:Komponent niestandardowy nie wyświetla zagnieżdżonych komponentów

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

exampleControl odda w porządku, ale zagnieżdżone rozpiętość nie będzie. Mój podstawowy kod renderujący jest:

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"); 
    } 
} 

Mam nawet próbował użyć konkretnej funkcji renderowania pożyczoną od renderujących Extension Library (funkcje użytkowe w AbstractApplicationLayoutRenderer.java) ale component.getChildCount() zawsze zwraca 0.

Dlaczego więc zagnieżdżone kontrolki nie wyświetlają, a czego mi brakuje?

+2

Czy sprawdziłeś Renderer.encodeChildren? AFAIK to nic nie robi - dlatego trzeba go zastąpić, więc połączenie z "super" nic nie robi. Przynajmniej musisz ustawić rendersChildren [na true] (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

Odpowiedz

7

W końcu to rozgryzłem. Kod Renderer był nieco czerwony śledzia, ponieważ, jak skomentował Stephan (stwissel), Renderer.encodeChildren nie robi nic. Patrząc na źródło kilku składników ExtLib, żaden z nich go nie używa.

Zmiana, którą wprowadziłem, dotyczyła klasy rozszerzenia. Po przeczytaniu bloga Keitha Stricklanda (http://www.keithstric.com/A55BAC/keithstric.nsf/default.xsp?documentId=82770C11FA7B9B21852579C100581766) i przejrzeniu com.ibm.xsp.extlib.component.layout.UIVarPublisherBase zaimplementowałem interfejs FacesComponent. W szczególności chciałem wywołać metodę buildContents, która wywołuje moduł FacesComponentBuilder. Javadoc dla FacesComponent ma do powiedzenia o FacesComponent:

buildContents Budowanie dzieci elementów i aspektów, domyślna implementacja jest zwykle: builder.buildAll (kontekst tego, true); // includeFacets = true

Moja klasa przedłużenie skończyło się patrząc tak:

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  

} 
} 

Obecnie wydaje się działać jak chciałem.

Na marginesie, inne obiekty w ExtLib (konkretnie UIWidgetContainer i UIList) mają różne sposoby renderowania swoich dzieci bez implementacji FacesComponent. To prawdopodobnie wymaga wpisu na blogu.

+2

cieszę się, że to wymyśliłeś i że udało mi się pomóc. Próbowałem odpowiedzieć wcześniej, ale miałem problemy z uwierzytelnianiem. – keithstric

Powiązane problemy