2013-01-25 19 views
6

Tôi đang cố gắng thực hiện một loại trang xem tin tức có thể tùy chỉnh đơn giản trong ứng dụng web của mình, như Google's one nhưng đơn giản hơn nhiều, với khung. Mỗi đối tượng khung đơn giản có tiêu đề của anh ta và một url được thêm vào làm nội dung của nó.Thủ công nhiều bảng nội dung động sẽ được hiển thị

Tôi đang sử dụng JSF và các nguyên tố, cả trên phiên bản mới nhất của chúng. Vì vậy, đậu ủng hộ của tôi, là @ViewScoped, có quyền truy cập vào người dùng đã đăng nhập, được lưu trữ trong một bean @SessionScoped và người dùng đó đã tải các khung tương ứng của mình.

Sự cố xảy ra khi tôi cố gắng lặp lại nó trên hạt @ViewScoped, bởi vì cách duy nhất tôi tìm thấy để làm điều đó là với thẻ c:forEach. Đó là cách tôi làm:

<ui:composition xmlns="http://www.w3.org/1999/xhtml" 
xmlns:ui="http://java.sun.com/jsf/facelets" 
xmlns:f="http://java.sun.com/jsf/core" 
xmlns:h="http://java.sun.com/jsf/html" 
xmlns:c="http://java.sun.com/jsp/jstl/core" 
xmlns:p="http://primefaces.org/ui" 
xmlns:fn="http://java.sun.com/jsp/jstl/functions"> 
<h:form> 
    <p:panel header="Noticias"> 
     <h:panelGrid columns="#{fn:length(navegableHomeManager._UserFrames)}" 
      width="100%"> 
      <c:forEach var="frame" items="#{navegableHomeManager._UserFrames}"> 
       <p:column> 
        <p:panel header="#{frame._Name}" closable="true" 
         style="width:95%;height:500px;" id="#{frame._Name}"> 
         <p:ajax event="close" 
          listener="#{navegableHomeManager.actionFrameClosed}" /> 
         <ui:include src="#{frame._Path}" /> 
        </p:panel> 
       </p:column> 
      </c:forEach> 
     </h:panelGrid> 
    </p:panel> 
</h:form> 

rằng lặp obviusly không làm việc với navegableHomeManager đậu vì nó là @ViewScoped. Vì vậy, đậu sẽ được xây dựng lại trong mỗi lần lặp lại. Giải pháp mà tôi đã đạt được sử dụng một hạt khác là @SessionScoped giữa các số navegableHomeManagerloggedBean, sao cho các khung được lưu trữ ở đó và tôi có thể có quyền truy cập vào các khung đó một cách chính xác vào lặp lại. Đó là làm việc với mã ở trên.

Tuy nhiên, tôi không nghĩ rằng bắt buộc phải sử dụng hạt đậu @SessionScoped (tạo một bean cụ thể cho từng trường hợp) mỗi khi tôi muốn lặp lại theo cách đó. Đó là lý do tại sao tôi đã thử sử dụng các thành phần để tránh lặp lại.

<p:dataGrid columns="#{fn:length(navegableHomeManager._UserFrames)}" 
      value="#{navegableHomeManager._UserFrames}" var="frame"> 
    <p:column> 
     <p:panel header="#{frame._Name}" closable="true" 
        style="width:95%;height:500px;"> 
      <p:ajax event="close" 
         listener="#{navegableHomeManager.actionFrameClosed}" /> 
      <ui:include src="#{frame._Path}" /> 
     </p:panel> 
    </p:column> 
</p:dataGrid> 

Nó không làm việc không phải khi đậu là @ViewScoped hoặc @SessionScoped, bởi vì ngay cả các thuộc tính khung được thiết lập, thẻ ui:include đã được xây dựng với không có đường dẫn đích, vì vậy tôi không thể làm cho điểm đến con đường thực tế. Tôi nghĩ rằng, như ui:include đang được áp dụng cùng lúc với c:forEach, sử dụng thẻ c:forEach thực sự là cách duy nhất để thực hiện điều này.

Tạo ý tưởng cho bạn.

CẬP NHẬT

Ở đây tôi gửi hơn xhtml mã để giúp đỡ trong sự hiểu biết về bối cảnh. Trang mới được tích hợp vào một mẫu. Đó là trang được nhắm mục tiêu (/system/home/index.xhtml):

<ui:composition xmlns="http://www.w3.org/1999/xhtml" 
template="/templates/general_template.xhtml" 
xmlns:ui="http://java.sun.com/jsf/facelets" 
xmlns:f="http://java.sun.com/jsf/core" 
xmlns:c="http://java.sun.com/jsp/jstl/core"> 

<ui:define name="metadata"> 
    <f:event type="preRenderView" 
     listener="#{navegableHomeManager.initialize}" /> 
</ui:define> 

<ui:define name="general_content"> 
    <ui:include src="/system/home/home_view.xhtml" /> 
</ui:define> 

Và đó là cách tôi cũng đã cố gắng để làm điều đó, nhưng không phải làm thẻ c:forEach làm việc:

<context-param> 
    <param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name> 
    <param-value>/system/home/index.xhtml</param-value> 
</context-param> 

Và đó là tiêu đề đậu ủng hộ:

@ManagedBean 
@ViewScoped 
@URLMapping(id = "home", pattern = "/home", viewId = "/system/home/index.xhtml") 
public class NavegableHomeManager extends SystemNavegable { 

/** 
* 
*/ 
private static final long serialVersionUID = 6239319842919211716L; 

@ManagedProperty(value = "#{loggedBean}") 
private LoggedBean _LoggedBean; 

//More stuff 

Trả lời

6

Dính vào <c:forEach>. Nó làm công việc bạn đang tìm kiếm. Các <ui:include> chạy trong thời gian xây dựng chế độ xem, do đó, thẻ lặp lại cũng sẽ chạy trong thời gian xây dựng chế độ xem.

Đối với vấn đề @ViewScoped đậu, bạn đã 2 lựa chọn:

  1. Tắt nhà nước một phần tiết kiệm cho xem cụ thể:

    <context-param> 
        <param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name> 
        <param-value>/news.xhtml</param-value> 
    </context-param> 
    
  2. Thay đổi nó vào một đậu @RequestScoped và sử dụng <f:param>@ManagedProperty để duy trì trạng thái qua đăng lại theo thông số yêu cầu.

Sẽ có tùy chọn thứ ba nếu JSF 2.2 khả dụng: chỉ cần nâng cấp lên JSF 2.2. Họ đã cố định vấn đề về trứng gà trong đậu rang và tiết kiệm một phần của tiểu bang.

+0

Cảm ơn câu trả lời. Vì một lý do nào đó, giải pháp dựa trên 'context-param' không hoạt động. 'navegableHomeManager' đang khôi phục ngay các khung trực tiếp từ' loggedBean', nhưng thẻ 'forEach' không thực hiện phép lặp lại ngay cả' # {fn: length (navegableHomeManager._UserFrames)} 'trả về' 1'. Đậu chỉ được xây dựng khi tôi truy cập trang, đó là chính xác. Tôi cũng không thể nâng cấp lên JSF 2.2 vì không có bản phát hành ổn định và tôi không thể tin tưởng vào nó 100%. –

+0

Về ngữ cảnh, rõ ràng bạn đã chỉ định ID chế độ xem sai (lưu ý: ID chế độ xem không phải là URL, đó là đường dẫn tương đối ngữ cảnh đến tệp thực, vì vậy ngay cả khi bạn ánh xạ điều JSF của mình trên '* .jsf', bạn vẫn nên sử dụng '.xhtml' trong ID chế độ xem). Như để phần còn lại, xin lỗi thật khó để hiểu được vấn đề dựa trên các thông tin cung cấp cho đến nay. – BalusC

+0

Tôi đã cập nhật câu hỏi thêm mã BalusC của tôi. Hy vọng nó sẽ giúp. –