2009-08-04 3 views
2

예상대로 작동한다고 생각할 수있는 많은 다른 것들을 시도해 왔습니다. 그러나, 그들은 나에게 약간의 좌절감을 안겨주고있다. 다음은 특종입니다 :ice : commandButton 구성 요소를 동적으로 생성

Java EE 웹 응용 프로그램에서 ICEFaces 1.8 구성 요소를 사용하고 있습니다. 내 목표는 내 데이터베이스에 대한 쿼리를 기반으로 페이지에서 commandButtons 얼음을 잔뜩 렌더링하는 것입니다. 이 버튼들이 나중에 데이터베이스에 대한 다른 쿼리의 매개 변수 (기본적으로 사용자 집합에 대한 쿼리 프론트 엔드)에 사용할 선택 항목을 전환 할 수 있기를 바랍니다. 그래서처럼 보이도록 출력을 싶습니다 내가 버튼을 만들 때

Selected

: 나는 버튼을 클릭하면 내 페이지에 다음 업데이트를하고 싶은

Deselected

정적으로 내 페이지에서 같은 :

<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" /> 

이 잘 작동하고, 각 버튼 내가 하시다 개별적으로 작동 uld는 기대한다. 내 백킹 빈이 업데이트되고, 매개 변수가 updateSeasons() 메소드에 올바르게 추가되고, 결과물이 올바른 레코드를 생성합니다.

그러나 나는 이것이 내가 원하는 것이 아니라는 것을 알고 있습니다. 다른 시즌이 시스템에 입력 될 때마다이를 업데이트하고 싶지 않습니다. 유지 보수 악몽 맞지?

그래서 내가하고 싶은 일은 동적으로 다음과 같은 Ice를 생성하는 것입니다 : commandButton 구성 요소는 Season 객체로 가득 찬 데이터베이스 테이블을 기반으로합니다. 다음은 내가 사용하는 시즌 수업입니다.

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

매우 간단합니다. 데이터베이스에서 유일해야한다는 두 가지 속성이 있습니다. 그래서 여기

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일 오후 2시 28분 11초 com.sun.faces.lifecycle.Phase doPhase SEVERE : JSF1054 : (상 ID : RENDER_RESPONSE 6,보기 ID : /phase1.jspx) 예외 단계에서 발생 execution : javax.faces.event.PhaseEvent [source = [email protected]] 2009 년 8 월 4 일 오후 2:28:11 org.apache.catalina.core.StandardWrapperValve 호출 심각도 : 서블릿. 서블릿 Persistent Faces 서블릿에 대한 service()는 예외를 던졌습니다 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) (com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle (Parser.java:204) , com.icesoft.faces.webapp.parser.Parser). executeJspLifecycle (Parser.java:229) at com.i 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) 에서 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.executeJspLifecycle (Parser.java:229) 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) com.icesoft.faces.application.D2DViewHandler.renderView (D2DViewHandler.java:153) at com.sun.faces.lifecycle.RenderResponsePhase.execute (RenderResponsePhase.execute : 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) com.icesoft.faces.context.View $ 2 $ 1.respond (View.java:47) at com.icesoft.fac es.webapp.http.servlet.ServletRequestResponse.respondWith (ServletRequestResponse.java:197) com.icesoft.faces.webapp.http.servlet.ThreadBlockingAdaptingServlet $ ThreadBlockingRequestResponse.respondWith (ThreadBlockingAdaptingServlet.java:36) 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. service (MainSessionBoundServlet.java:114) 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) 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) com.icesoft.faces.webapp.http.servlet.PathDispatcher.service (PathDispatcher.java:23) at com.icesoft .faces.webapp.http.servlet.MainServlet.service (MainServlet.java:153) (javax.servlet.http.HttpServlet.service (HttpServlet.자바 : org.apache에서 org.apache.catalina.core.ApplicationFilterChain.doFilter에서 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:290) 에서 717) (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) at org.apache.catalina.valves.ErrorReportValve.invoke (ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke (StandardEngineValve.java:109) at 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

java.lang.Thread.run (Thread.java:619)

에서 .net.JIoEndpoint $ Worker.run (JIoEndpoint.java:447) 는 내가 일을하지 말아야 뭔가를하려고?

이 목표를 달성하는 더 좋은 방법이 있습니까?

추가 정보가 필요하면 제공 해줘서 기쁩니다.

미리 감사드립니다.

UPDATE :

<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() 메소드를 변경 :

그래서 나는 목록에 목록에서 seasonsList 수집을 변경하고 일부 다른 마크 업을 렌더링과 같이 시도

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

실제로보고 싶은 모든 버튼을 렌더링하고이를 정확하게 selec에 추가합니다. tedSeasonsList를 클릭하면 해당 백킹 빈에 있고, 다시 클릭하면 해당 백에서 제거됩니다.

그러나 UI에서 버튼 하나만 누르면 토글됩니다. 예를 들어, I 2009-2010 클릭하면, 이것은 내가 볼 것입니다 :

All Selected

답변

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

바인딩 속성은 유형 UIComponent의 빈 속성에 바인딩해야합니다. 이는 프레임 워크가 Backing Bean의 구성 요소에 대한 참조를 제공하거나 Backing 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는 clientId (read this for more detail)를 사용하여 클라이언트에서의 고유성을 보장 처리됩니다.


편집 :

그러나, UI에 모든 버튼이 난 그냥 하나 개의 버튼을 클릭 할 때 전환 할 것으로 보인다.

좀 반복 컨트롤 (예를 들어, 데이터 테이블을)처럼 ice:panelSeries 모든 행의 구성 요소 상태를 저장하지 않는 것을 추측하고있다. "행"당 한 번 인코딩/디코딩 되더라도 하나의 버튼 인스턴스 만 있습니다.

나는 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> 

따라서, 귀하의 목록에있는 각 항목에 대한 모든 바인딩은 한 국가의 조각 (A SelectionBean 예) 당신에게 돌아갑니다 구성 요소 i에 선언적이 아닌 상태를 저장하지 마십시오. tself.

내가 할 수있는 경우 이상을 사용하려고 시도합니다. POJO에서 JSF 항목을 유지합니다.

+0

HtmlCommandButton은 UIComponent를 확장 했으므로 ... – karlgrz

+0

또한, 이후에 업데이트 된 ActionListener 속성에서 Phase1EventBean을 잘못 사용했습니다. 내 사과. – karlgrz

+0

아, HtmlCommandButton이 올바른 유형입니다. 흠. 바인딩의 표현은 "지정된 ValueExpression이 UIComponent (또는 적절한 하위 클래스) 유형의 읽기 - 쓰기 JavaBeans 속성을 가리켜 야합니다." "var"수에 바인딩하는 경우 확실하지 않습니다. – McDowell

관련 문제