2013-04-05 32 views
7

Tôi đang làm việc với trang tổng quan động nơi người dùng có thể ghim và xóa các mục theo ý muốn. Bây giờ tôi có một vấn đề mà tôi muốn thêm thành phần hỗn hợp hiện có vào khung nhìn từ bean sao lưu. Tôi đã cố gắng tìm cách chính xác để làm điều này từ internet nhưng không thành công cho đến nay. Đây là thành phần hỗn hợp đơn giản tôi muốn thêm:Tạo và thêm thành phần hỗn hợp theo cách lập trình trong bean sao lưu

<?xml version='1.0' encoding='UTF-8' ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" 
     xmlns:cc="http://java.sun.com/jsf/composite" 
     xmlns:ui="http://java.sun.com/jsf/facelets" 
     xmlns:h="http://java.sun.com/jsf/html" 
     xmlns:f="http://java.sun.com/jsf/core" 
     xmlns:p="http://primefaces.org/ui" 
     xmlns:composite="http://java.sun.com/jsf/composite"> 
    <!-- INTERFACE --> 
    <cc:interface> 

    </cc:interface> 

    <!-- IMPLEMENTATION --> 
    <cc:implementation> 
     <h:outputText value="TEST"/> 
    </cc:implementation> 
</html> 

Đây là mã mà nên trả lại các thành phần tổng hợp:

public static UIComponent getCompositeComponent(String xhtml, String namespace) { 
    FacesContext fc = FacesContext.getCurrentInstance(); 
    Application app = fc.getApplication(); 
    Resource componentResource = app.getResourceHandler().createResource(xhtml, namespace); 

    UIPanel facet = (UIPanel) app.createComponent(UIPanel.COMPONENT_TYPE); 
    facet.setRendererType("javax.faces.Group"); 
    UIComponent composite = app.createComponent(fc, componentResource); 
    composite.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, facet); 

    return composite; 
} 

Và đây là làm thế nào tôi đang sử dụng các chức năng:

Column column = new Column(); 
UIComponent test = HtmlUtil.getCompositeComponent("test.xhtml", "comp"); 
column.getChildren().add(test); 

Nhưng không có gì được hiển thị bên trong cột. Bất kỳ ý tưởng làm thế nào điều này có thể được thực hiện? Tôi không muốn đi với cách render = "# {bean.isThisRendered}" bởi vì nó không phù hợp với trường hợp sử dụng của tôi.

+0

Ra quan tâm (chủ đề được khủng khiếp xấu bao phủ và điều này sẽ mang lại cho tôi nhiều năm phía trước ánh sáng): Có thì bạn gọi các 3-liner gọi 'HtmlUtil.getCompositeComponent'? –

Trả lời

11

Mã này chưa hoàn chỉnh. Bạn cần sử dụng FaceletContext#includeFacelet() sau đó để bao gồm tài nguyên thành phần tổng hợp trong việc triển khai thành phần hỗn hợp. Đây là một phương pháp tiện ích thực hiện công việc. Điều quan trọng là phải có cha mẹ trong tầm tay, vì nó là bối cảnh nơi mà các #{cc} nên được tạo ra trong phạm vi EL. Vì vậy, phương pháp tiện ích này cũng ngay lập tức thêm hỗn hợp làm con của cha mẹ đã cho. Hơn nữa, điều quan trọng là cung cấp cho thành phần hỗn hợp một ID cố định, nếu không JSF sẽ không thể xử lý bất kỳ thành phần biểu mẫu/đầu vào/lệnh nào bên trong hỗn hợp.

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

Vì vậy, trong ví dụ cụ thể của bạn, sử dụng nó như sau:

includeCompositeComponent(column, "comp", "test.xhtml", "someUniqueId"); 
+0

Rất thú vị! Có thể sử dụng phương pháp này (có thể một chút thay đổi) để bao gồm các thành phần bên ngoài? Thay vì sử dụng tài nguyên hiện có, tôi muốn bao gồm các thành phần không được xác định trong ứng dụng. – fnst

+1

@fnst: Bạn có thể nếu cần kiểm soát việc xử lý tài nguyên bằng trình xử lý tài nguyên tùy chỉnh. Miễn là cuối cùng bạn kết thúc với một 'URL' hợp lệ, về cơ bản nó có thể trỏ tới mọi thứ (bao gồm' file: // ',' http: // ', vv và thậm chí cả các giao thức tùy chỉnh sao cho truy cập DB về lý thuyết có thể) . – BalusC

+0

Cảm ơn câu trả lời của bạn, phải thử điều đó :) Có thể thêm biểu thức giá trị làm thuộc tính cho các thành phần hỗn hợp không? – drodil

Các vấn đề liên quan