JSF 2

2011-03-20 19 views
10

'da bileşik bir bileşen nasıl programlanır veya dinamik olarak oluşturulur JSF 2'de bileşen bileşenleri programlı olarak oluşturmalıyım. Arama ve denemelerden birkaç gün sonra bu yöntemi anladım (java.net'ten Lexi'den ilham alarak):JSF 2

/** 
* Method will attach composite component to provided component 
* @param viewPanel parent component of newly created composite component 
*/ 
public void setComponentJ(UIComponent viewPanel) { 
    FacesContext context = FacesContext.getCurrentInstance(); 
    viewPanel.getChildren().clear(); 

    // load composite component from file 
    Resource componentResource = context.getApplication().getResourceHandler().createResource("whatever.xhtml", "components/form"); 
    UIComponent composite = context.getApplication().createComponent(context, componentResource); 

    // push component to el 
    composite.pushComponentToEL(context, composite); 
    boolean compcompPushed = false; 
    CompositeComponentStackManager ccStackManager = CompositeComponentStackManager.getManager(context); 
    compcompPushed = ccStackManager.push(composite, CompositeComponentStackManager.StackType.TreeCreation); 

    // Populate the component with value expressions 
    Application application = context.getApplication(); 
    composite.setValueExpression("value", application.getExpressionFactory().createValueExpression(
      context.getELContext(), "#{stringValue.value}", 
      String.class)); 

    // Populate the component with facets and child components (Optional) 
    UIOutput foo = (UIOutput) application.createComponent(HtmlOutputText.COMPONENT_TYPE); 
    foo.setValue("Foo"); 
    composite.getFacets().put("foo", foo); 
    UIOutput bar = (UIOutput) application.createComponent(HtmlOutputText.COMPONENT_TYPE); 
    bar.setValue("Bar"); 
    composite.getChildren().add(bar); 

    // create composite components Root 
    UIComponent compositeRoot = context.getApplication().createComponent(UIPanel.COMPONENT_TYPE); 
    composite.getAttributes().put(Resource.COMPONENT_RESOURCE_KEY, componentResource); 
    compositeRoot.setRendererType("javax.faces.Group"); 
    composite.setId("compositeID"); 

    try { 
     FaceletFactory factory = (FaceletFactory) RequestStateManager.get(context, RequestStateManager.FACELET_FACTORY); 
     Facelet f = factory.getFacelet(componentResource.getURL()); 
     f.apply(context, compositeRoot); //<==[here] 
    } catch (Exception e) { 
     log.debug("Error creating composite component!!", e); 
    } 
    composite.getFacets().put(
      UIComponent.COMPOSITE_FACET_NAME, compositeRoot); 

    // attach composite component to parent componet 
    viewPanel.getChildren().add(composite); 

    // pop component from el 
    composite.popComponentFromEL(context); 
    if (compcompPushed) { 
     ccStackManager.pop(CompositeComponentStackManager.StackType.TreeCreation); 
    } 
} 

Sorun şu ki, bu kod benim için sadece javax.faces.PROJECT_STAGE PRODUCTION olarak ayarlandığında benim için işe yaradı (bunu çözmek bütün günümü aldı). javax.faces.PROJECT_STAGE GELİŞTİRME İstisna olarak ayarlanırsa ([buradan] < ==) belirgin noktada atılır:

javax.faces.view.facelets.TagException: /resources/components/form/pokus.xhtml @8,19 <cc:interface> Component Not Found for identifier: j_id2.getParent(). 
    at com.sun.faces.facelets.tag.composite.InterfaceHandler.validateComponent(InterfaceHandler.java:135) 
    at com.sun.faces.facelets.tag.composite.InterfaceHandler.apply(InterfaceHandler.java:125) 
    at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:98) 
    at com.sun.faces.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:93) 
    at com.sun.faces.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:82) 
    at com.sun.faces.facelets.impl.DefaultFacelet.apply(DefaultFacelet.java:152) 
    at cz.boza.formcreator.formcore.Try.setComponentJ(Try.java:83) 
    at cz.boza.formcreator.formcore.FormCreator.<init>(FormCreator.java:40) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:532) 

O (j_id2 otomatik olarak compositeRoot kimliği üretilir) compositeRoot bileşeni ayarlanan ebeveyn ile bir sorun . Ayrıca bu kod yeterince güçlü bir şekilde test edilmiyor, bu yüzden ona güvenebileceğime emin değilim.

Kompozit Bileşenleri programatik olarak işlemek için çok önemli olduğunu düşünüyorum. Aksi halde Kompozit Parçalar yarı işe yaramaz.

Çok teşekkür ederim.

+0

bazı sonra JSF 2.2 kullanıyorsanız aşağıdaki gibi Yani, yaklaşım yapılmalıdır test ettim ki, diğer bileşenlerde herhangi bir bileşeni (çocuk olarak ekleyelim) programlayamadığımı da öğrendim :(. –

+1

Tamam Sonunda bir çözüm buldum. Burada, programlı olarak Bileşik Bileşenleri oluşturmak için demo ho indirebilirsiniz. /confluence.highsource.org/display/Hifaces20/Dynamic + Faces + - + sample + gösteren + dinamik + veya + programatik + UI + oluşturma + + JSF + 2.0 + ve + Facelets ile –

+0

denedim. Kompleks bileşenlerin programatik olarak oluşturulması ve JSF sayfalarının dinamik olarak oluşturulmasıyla ilgili tüm proje olduğu için karmaşıktır. –

cevap

7

Her iki çözüm de benim için işe yaramadığından, statik olarak yerleştirilmiş kompozitlerin bileşen ağacına nasıl eklendiğini ve işlendiğini öğrenmek için JSF uygulamasına giriyorum. Bu nihayet ile sona erdi çalışma kodudur:

public UIComponent addWidget(UIComponent parent, String widget) { 
    UIComponent cc = null; 
    UIComponent facetComponent = null; 
    FacesContext ctx = FacesContext.getCurrentInstance(); 
    Resource resource = ctx.getApplication().getResourceHandler().createResource(widget + ".xhtml", "widgets"); 
    FaceletFactory faceletFactory = (FaceletFactory) RequestStateManager.get(ctx, RequestStateManager.FACELET_FACTORY); 

    // create the facelet component 
    cc = ctx.getApplication().createComponent(ctx, resource); 

    // create the component to be populated by the facelet 
    facetComponent = ctx.getApplication().createComponent(UIPanel.COMPONENT_TYPE); 
    facetComponent.setRendererType("javax.faces.Group"); 

    // set the facelet's parent 
    cc.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, facetComponent); 

    // populate the facetComponent 
    try { 
     Facelet facelet = faceletFactory.getFacelet(resource.getURL()); 
     facelet.apply(ctx, facetComponent); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    // finally add the facetComponent to the given parent 
    parent.getChildren().add(cc); 

    return cc; 
} 
+0

Bu, türünde bir ' 'seçeneğine güveniyorsa başarısız olur. – BalusC

14

ben ayrıntılı olarak beton sorunu açıklayamam, ama sadece gözlemlemek ve söz konusu gösterilen yaklaşım beceriksiz ve sıkı bağlanmış olduğunu teyit edebilir Mojarra. Mojarra gerektiren com.sun.faces.* belirli bağımlılıklar vardır. Bu yaklaşım standart API yöntemlerini kullanmamaktadır ve ek olarak MyFaces gibi diğer JSF uygulamalarında da çalışmayacaktır. Standart API tarafından sağlanan yöntemler kullanılarak çok daha basit bir yaklaşım sunulmuştur. Anahtar nokta, belirtilen üst öğeye bileşik bileşen kaynağını eklemek için FaceletContext#includeFacelet() kullanmanız gerektiğidir.

public static void includeCompositeComponent(UIComponent parent, String libraryName, String resourceName, String id) { 
    // Prepare. 
    FacesContext context = FacesContext.getCurrentInstance(); 
    Application application = context.getApplication(); 
    FaceletContext faceletContext = (FaceletContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY); 

    // This basically creates <ui:component> based on <composite:interface>. 
    Resource resource = application.getResourceHandler().createResource(resourceName, libraryName); 
    UIComponent composite = application.createComponent(context, resource); 
    composite.setId(id); // Mandatory for the case composite is part of UIForm! Otherwise JSF can't find inputs. 

    // This basically creates <composite:implementation>. 
    UIComponent implementation = application.createComponent(UIPanel.COMPONENT_TYPE); 
    implementation.setRendererType("javax.faces.Group"); 
    composite.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, implementation); 

    // Now include the composite component file in the given parent. 
    parent.getChildren().add(composite); 
    parent.pushComponentToEL(context, composite); // This makes #{cc} available. 
    try { 
     faceletContext.includeFacelet(implementation, resource.getURL()); 
    } catch (IOException e) { 
     throw new FacesException(e); 
    } finally { 
     parent.popComponentFromEL(context); 
    } 
} 

aşağıdaki şekilde kullanmak, URI'dan xmlns:my="http://java.sun.com/jsf/composite/mycomponents" den <my:testComposite id="someId"> dahil etmek istediğinizi varsayalım:

includeCompositeComponent(parent, "mycomponents", "testComposite.xhtml", "someId"); 

Bu aynı zamanda (V1.5 beri) Components#includeCompositeComponent() MTU yarar kütüphanesine OmniFaces eklenmiştir.


Güncelleme JSF 2.2 beri ViewDeclarationLanguage sınıfı da bu amaç için kullanılabilir taglib URI ve etiket adı alarak yeni createComponent() yöntemi var.

public static void includeCompositeComponent(UIComponent parent, String taglibURI, String tagName, String id) { 
    FacesContext context = FacesContext.getCurrentInstance(); 
    UIComponent composite = context.getApplication().getViewHandler() 
     .getViewDeclarationLanguage(context, context.getViewRoot().getViewId()) 
     .createComponent(context, taglibURI, tagName, null); 
    composite.setId(id); 
    parent.getChildren().add(composite); 
} 

sonra, URI'dan xmlns:my="http://xmlns.jcp.org/jsf/composite/mycomponents" den <my:testComposite id="someId"> dahil etmek istediğiniz düşünün aşağıdaki gibi kullanabilirsiniz:

includeCompositeComponent(parent, "http://xmlns.jcp.org/jsf/composite/mycomponents", "testComposite", "someId"); 
+0

Merhaba. Ben de konuyla yüzleşiyorum; Facelet dinamik oluşturma örnek tam olarak jsf 2.0 için Tamam mı? Çünkü bu satırda NPE ile karşılaşıyorum '* .getAttributes(). Get (FaceletContext.FACELET_CONTEXT_KEY);' – user390525