2009-08-04 58 views
2

我一直在嘗試很多不同的事情,我認爲它們可以像預期的那樣工作。但是,他們讓我感到沮喪。這裏是獨家新聞:動態生成ice:commandButton組件

我在Java EE web應用程序中使用ICEFaces 1.8組件。我的目標是根據對數據庫的查詢呈現一堆ice:commandButtons。我希望這些按鈕能夠切換稍後我將用於參數的選擇到數據庫的另一個查詢(基本上是針對一組用戶的查詢前端)。我想輸出看起來像這樣:

Deselected

當我點擊一個按鈕,我想下面的更新到我的網頁:

Selected

當我創建的按鈕在我的頁面上靜態地,因此:

<ice:commandButton id="seasonSEP09" style="background-color: #FFFFFF;" partialSubmit="true" actionListener="#{bean.updateSeasons}" value="2009-2010" /> 
<ice:commandButton id="seasonSEP08" style="background-color: #FFFFFF;" partialSubmit="true" actionListener="#{bean.updateSeasons}" value="2008-2009" /> 
<ice:commandButton id="seasonSEP07" style="background-color: #FFFFFF;" partialSubmit="true" actionListener="#{bean.updateSeasons}" value="2007-2008" /> 
<ice:commandButton id="seasonSEP06" style="background-color: #FFFFFF;" partialSubmit="true" actionListener="#{bean.updateSeasons}" value="2006-2007" /> 

這很好,每個按鈕單獨工作,因爲我窩呃期望。我的支持bean被更新,參數被正確添加到updateSeasons()方法中,並且我的輸出在最後產生正確的記錄。

但是,我知道這不是我想要的。我不想在系統中輸入另一個賽季的時候隨時更新這些信息。維護噩夢,對吧?

所以我想要做的是動態生成這些ice:commandButton組件基於我的數據庫表充滿季節對象。這裏是我正在使用的季節類:

public class Season 
{ 
    String StartMonth; 
    String Season; 

    public String getStartMonth() 
    { 
     return StartMonth; 
    } 
    public void setStartMonth(String startMonth) 
    { 
     StartMonth = sweep; 
    }  
    public void setSeason(String season) 
    { 
     Season = season; 
    } 
    public String getSeason() 
    { 
     return Season; 
    } 
} 

非常簡單。兩個屬性,我保證在數據庫中是唯一的。

下面是支持bean我使用:

public class Bean 
{ 
    public Bean() 
    { 
     defineSeasonsList(); 
    } 

    public List<HtmlCommandButton> seasonsList; 

    // seasonsList getter & setter omitted 

    public List<String> selectedSeasons; 

    // selectedSeasons getter & setter omitted 

    private void defineSeasonsList() 
    { 
     seasonsList = new ArrayList<HtmlCommandButton>(); 
     selectedSeasons = new ArrayList<String>(); 

     try 
     { 
      hibernate.openTransaction(); 

      for(Season season:defineSeasonsListFromDataSource())) 
      { 
       HtmlCommandButton button = new HtmlCommandButton(); 

       button.setId("season" + season.getStartMonth()); 
       button.setValue(season.getSeason); 
       button.setStyle("background-color: #FFFFFF;"); 
       button.setPartialSubmit(true); 

       seasonsList.add(button); 
      }       
     } 
     catch (Exception e) 
     { 
      System.out.println("Error defining seasons list: " + e.getMessage()); 
     } 
     finally 
     { 
      hibernate.commitTransaction(); 
     }    
    } 

    public void updateSeasons(ActionEvent ae) 
    { 
     HtmlCommandButton selected = (HtmlCommandButton) ae.getComponent(); 

     if(selectedSeasons.contains(selected.getValue().toString())) 
     { 
      selectedSeasons.remove(selected.getValue().toString()); 
      selected.setStyle("background: #FFFFFF;"); 
     } 
     else 
     { 
      selectedSeasons.add(selected.getValue().toString()); 
      selected.setStyle("background: #009DD9; color: #FFFFFF;"); 
     } 
    } 
} 

好了,這纔是我的困境(一個或多個)。

首先,我試圖使這個標記:

<p> 
    <ice:panelGroup> 
     <ice:panelSeries id="seasonsList" value="#{bean.seasonsList}" var="season"> 
       <ice:commandButton binding="#{season}"/>           
     </ice:panelSeries> 
    </ice:panelGroup> 
</p>  

而且我得到這樣的輸出:

Bad Buttons

所以,感到沮喪和冒險,我試圖使這個標記來實現我的目標是:

<p> 
    <ice:panelGroup> 
     <ice:panelSeries id="seasonsList" value="#{bean.seasonsList}" var="season"> 
       <ice:commandButton id="#{season.id}" partialSubmit="true" style="background-color: #FFFFFF" value="#{season.value}" actionListener="#{bean.updateSeasons}"/>           
     </ice:panelSeries> 
    </ice:panelGroup> 
</p> 

其中產生以下stac的ktrace:

2009年8月4日下午二時28分11秒com.sun.faces.lifecycle.Phase doPhase 重度:JSF1054:(階段ID:RENDER_RESPONSE 6,查看ID:/phase1.jspx)異常階段期間拋出執行:javax.faces.event.PhaseEvent [source = [email protected]] 2009年8月4日下午2時28分11秒org.apache.catalina.core.StandardWrapperValve調用 SEVERE:Servlet。 servlet的service()持久Faces Servlet拋出異常 java.lang.IllegalArgumentException:#{season.id} at javax.faces.component.UIComponentBase.validateId(UIComponentBase。的java:549) 在javax.faces.component.UIComponentBase.setId(UIComponentBase.java:351) 在javax.faces.webapp.UIComponentTag.createComponent(UIComponentTag.java:219) 在javax.faces.webapp.UIComponentClassicTagBase。 createChild所(UIComponentClassicTagBase.java:486) 在javax.faces.webapp.UIComponentClassicTagBase.findComponent(UIComponentClassicTagBase.java:670) 在javax.faces.webapp.UIComponentClassicTagBase.doStartTag(UIComponentClassicTagBase.java:1142) 在com.icesoft。 faces.component.CommandButtonTag.doStartTag(CommandButtonTag.java:741) at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:204) at com.icesoft.faces.webapp.parser.Parser。 executeJspLifecycle(Parser.java:229) at com.i cesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229) at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229) at com.icesoft.faces.webapp。 parser.Parser.executeJspLifecycle(Parser.java:229) at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229) at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle( Parser.java:229) 在com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229) 在com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229) at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229) at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229) at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229) at com.icesoft.faces.webapp.parser.Parser.parse(Parser.java:162) at com.icesoft.faces .application.D2DViewHandler.renderResponse(D2DViewHandler.java:464) at com.icesoft.faces.application.D2DViewHandler.renderView(D2DViewHandler.java:153) at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java :110) at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100) at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) at com.icesoft.faces .webapp.http.core.JsfLifecycleExecutor.apply(JsfLifecycleExecutor.java:17) at com.icesoft.faces.context.View $ 2 $ 1.respond(View.java:47) at com.icesoft.fac es.webapp.http.servlet.ServletRequestResponse.respondWith(ServletRequestResponse.java:197) at com.icesoft.faces.webapp.http.servlet.ThreadBlockingAdaptingServlet $ ThreadBlockingRequestResponse.respondWith(ThreadBlockingAdaptingServlet.java:36) at com.icesoft。 faces.context.View $ 2.serve(View.java:72) at com.icesoft.faces.context.View.servePage(View.java:133) at com.icesoft.faces.webapp.http.core.SingleViewServer .service(SingleViewServer.java:52) at com.icesoft.faces.webapp.http.common.ServerProxy.service(ServerProxy.java:11)​​ at com.icesoft.faces.webapp.http.servlet.MainSessionBoundServlet $ 4。服務(MainSessionBoundServlet.java:114) at com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer.service(PathDispatcherServer.java:24) at com.icesoft.faces.webapp.http.servlet.MainSessionBoundServlet.service(MainSessionBoundServlet.java:160) at com.icesoft.faces.webapp.http.servlet.SessionDispatcher $ 1.service(SessionDispatcher.java:42) at com.icesoft.faces.webapp.http.servlet.ThreadBlockingAdaptingServlet.service(ThreadBlockingAdaptingServlet.java:19) at com.icesoft.faces.webapp.http.servlet.EnvironmentAdaptingServlet.service(EnvironmentAdaptingServlet.java:63) at com .icesoft.faces.webapp.http.servlet.SessionDispatcher.service(SessionDispatcher.java:62) at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23) at com.icesoft .faces.webapp.http.servlet.MainServlet.service(MainServlet.java:153) at javax.servlet.http.HttpServlet.service(HttpServlet。的java:717) 在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) 在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 在org.apache。 catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve。的java:128) 在org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) 在org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 在org.apache。 catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286) 在org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845) at org.apache.coyote.http11.Http11Protocol $ Http11ConnectionHandler.process(Http11Protocol.java:583) at org.apache.tomcat.util .net.JIoEndpoint $ Worker.run(JIoEndpoint.java:447) at java.lang.Thread.run(Thread.java:619)

我想做一些我不應該做的事情嗎?

有沒有更好的方法來完成這個目標?

如果需要更多信息,我很樂意提供。

在此先感謝,我的朋友們。

UPDATE

所以,我想從列表改變seasonsList集合列表,並呈現一些不同的標記,就像這樣:

<p> 
    <ice:panelGroup> 
     <ice:panelSeries value="#{bean.seasonsList}" var="season"> 
       <ice:commandButton partialSubmit="true" style="background-color: #FFFFFF" value="#{season}" actionListener="#{Phase1EventBean.updateSeasons}"/>           
     </ice:panelSeries> 
    </ice:panelGroup> 
</p> 

和更改defineSeasonsList()方法:

public void defineNationalSeasonsList() 
{ 
    try 
    { 
     seasonsList = new ArrayList<String>(); 
     selectedSeasonsList = new ArrayList<String>(); 

     hibernate.openTransaction(); 

     for(UedaNationalDates season:hibernate.getList(new UedaNationalDates(), QueryFactory.getUedaNationalSeasons(hibernate.getHibSession()))) 
     { 
      nationalSeasonsList.add(season.getSeason()); 
     }  
    } 
    catch (Exception e) 
    { 
     System.out.println("Error defining nationalMeasurementPeriods: " + e.getMessage()); 
    } 
    finally 
    { 
     hibernate.commitTransaction(); 
    }    
} 

這實際上呈現我想看到的所有按鈕,並將它們正確地添加到選擇tedSeasonsList在我的支持bean中,當我點擊它們時,當我再次點擊時將它從它移除。

但是,在UI上,每個按鈕似乎都會在單擊一個按鈕時切換。例如,當我點擊2009- 2010年,這是我所看到的:

All Selected

回答

2
<ice:commandButton binding="#{season}"/> 

綁定屬性必須綁定到UIComponent類型的bean屬性。它用於你希望框架給你一個支持bean中的組件的引用或者從支持bean提供一個實例)。有關更多詳細信息,請參見JSF 1.2 spec的第3.1.5節。


<ice:commandButton id="#{season.id}" 
    partialSubmit="true" 
    style="background-color: #FFFFFF" 
    value="#{season.value}" 
    actionListener="#{Phase1EventBean.updateSeasons}"/> 

id屬性不能是動態的 - JSF將確保使用clientIdread this for more detail)在客戶端上其獨特的照顧。


編輯:

然而,在UI上,每一個按鈕出現,當我點擊只是一個按鈕進行切換。

我猜ice:panelSeries並不像每個重複控件所做的那樣存儲每一行​​的組件狀態(例如dataTable)。請記住,即使每個「行」編碼/解碼一次,也只有一個按鈕實例。

我從來沒有使用ICEfaces的,但我建議結合豆類與此類似:

public class Bean { 

    private final List<SelectionBean> seasonsList = Arrays.asList(
     new SelectionBean("Spring"), new SelectionBean("Summer"), 
     new SelectionBean("Autumn"), new SelectionBean("Winter")); 

    public List<SelectionBean> getSeasonsList() { return seasonsList; } 

    public static class SelectionBean { 

    private String season; 
    private boolean selected; 

    public SelectionBean() {} 
    public SelectionBean(String season) { this.season = season; } 

    public String getSeason() { return season; } 
    public void setSeason(String season) { this.season = season; } 

    public String toggle() { 
     System.out.println("toggle " + season); 
     selected = !selected; 
     return null; 
    } 

    public String getStyle() { 
     return selected ? "background-color: yellow" : "background-color: blue"; 
    } 
    } 
} 

我回吐邏輯降到最低限度,但希望你如何修改邏輯把休眠支持回那麼你的組件將成爲這樣的事情:

<ice:panelSeries value="#{bean.seasonsList}" var="item"> 
    <ice:commandButton partialSubmit="true" 
    style="#{item.style}" 
    value="#{item.season}" 
    action="#{item.toggle}"/>           
</ice:panelSeries> 

所以,在列表中的每個項目,所有的結合可以追溯到一件狀態(一SelectionBean實例)和你不要嘗試在組件i上存儲任何非聲明狀態自行宣佈。

我試着在actionListener以上使用action當我可以 - 它使JSF的東西保持在POJO之外。

+0

HtmlCommandButton擴展了UIComponent,雖然,或者所以我認爲... – karlgrz 2009-08-04 21:42:04