3

私は、期待どおりに機能すると思われるさまざまなことを試してきました。しかし、彼らは私にいくつかの不満を引き起こしています. ここにスクープがあります:

Java EE Web アプリケーションで ICEFaces 1.8 コンポーネントを使用しています。私の目標は、データベースへのクエリに基づいて、ページに一連の ice:commandButtons をレンダリングすることです。これらのボタンを使用して、後でパラメーターに使用する選択をデータベースへの別のクエリに切り替えられるようにしたいと考えています (基本的には、一連のユーザーに対する並べ替えのフロント エンドのクエリ)。出力を次のようにしたいと思います。

選択解除

ボタンをクリックしたときに、ページを次のように更新したいと考えています。

選択済み

ページに静的にボタンを作成したとき、次のようになります。

<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() メソッドに正しく追加され、最後の出力で正しいレコードが生成されます。

しかし、私はこれが私が望むものではないことを知っています。システムに別のシーズンが入力されるたびに、これらを更新したくありません。メンテナンスの悪夢ですね。

したがって、私がやりたいことは、Season オブジェクトでいっぱいのデータベース テーブルに基づいて、これらの 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;
    }
}

非常に簡単です。データベース内で一意であることが保証されている 2 つのプロパティ。

使用しているバッキング 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;");
        }
    }
}   

OK、ここに私のジレンマがあります。

まず、このマークアップをレンダリングしようとしました:

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

そして、私はこの出力を取得します:

悪いボタン

それで、欲求不満で冒険心が強いので、このマークアップをレンダリングして目標を達成しようとしました。

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

次のスタックトレースが得られました。

2009 年 8 月 4 日 2:28:11 PM com.sun.faces.lifecycle.Phase doPhase SEVERE: JSF1054: (フェーズ ID: RENDER_RESPONSE 6、ビュー ID: /phase1.jspx) フェーズ実行中にスローされる例外: javax.faces.event .PhaseEvent[source=com.sun.faces.lifecycle.LifecycleImpl@1a477b7] 2009 年 8 月 4 日 2:28:11 PM org.apache.catalina.core.StandardWrapperValve 呼び出し SEVERE: Servlet.service() for servlet Persistent Faces Servlet がスローされました例外 java.lang.IllegalArgumentException: #{season.id} at javax.faces.component.UIComponentBase.validateId(UIComponentBase.java:549) at javax.faces.component.UIComponentBase.setId(UIComponentBase.java:351) at javax. faces.webapp.UIComponentTag.createComponent(UIComponentTag.java:219) で javax.faces.webapp.UIComponentClassicTagBase.createChild(UIComponentClassicTagBase.java:486) で javax.faces.webapp.UIComponentClassicTagBase で。findComponent(UIComponentClassicTagBase.java:670) at 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) 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) com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229) com.icesoft.faces.webapp.パーサー。com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229) の 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) で com.icesoft.faces .webapp.parser.Parser.parse(Parser.java:162) com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:464) com.icesoft.faces.application.D2DViewHandler.renderView(D2DViewHandler.java) :153) com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110) で com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100) で com.sun.faces.lifecycle. LifecycleImpl.render(LifecycleImpl.java:139) com.icesoft.faces.webapp.http.core.JsfLifecycleExecutor.apply(JsfLifecycleExecutor.java:17) com.icesoft.faces.context.View$2$1.respond(View.java:47) com.icesoft .faces.webapp.http.servlet.ServletRequestResponse.respondWith(ServletRequestResponse.java:197) 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) の com.icesoft.faces.webapp.http.common.ServerProxy.service(ServerProxy.java:11) の com.icesoft.faces.webapp.http.servlet.MainSessionBoundServlet$4.service(MainSessionBoundServlet.java) :114) com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer.service(PathDispatcherServer.java:24) で com.icesoft.faces.webapp.http.servlet.MainSessionBoundServlet.service(MainSessionBoundServlet.java:160) でcom.icesoft.faces.webapp.http.servlet.SessionDispatcher$1.service(SessionDispatcher.java:42) で com.icesoft.faces.webapp.http.servlet.ThreadBlockingAdaptingServlet.service(ThreadBlockingAdaptingServlet.java:19) で com. icesoft.faces.webapp.http.servlet.EnvironmentAdaptingServlet.service(EnvironmentAdaptingServlet.java:63) com.icesoft.faces.webapp.http.servlet.SessionDispatcher.service(SessionDispatcher.java:62) com.icesoft.faces で。 webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23) com.icesoft.faces.webapp.http.servlet.MainServlet.service(MainServlet.java:153) で javax.org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) の servlet.http.HttpServlet.service(HttpServlet.java:717) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java: 206) org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) で org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) で 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. org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845) org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) で org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447) で java.lang .Thread.run(Thread.java:619)

私はしてはいけないことをしようとしていますか?

この目標を達成するためのより良い方法はありますか?

さらに情報が必要な場合は、喜んで提供します。

前もって感謝します、私の友達。

更新

そこで、seasonsList コレクションを List から List に変更して、次のように別のマークアップをレンダリングしてみました。

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

これにより、表示したいすべてのボタンが実際にレンダリングされ、クリックするとバッキング Bean の selectedSeasonsList に正しく追加され、もう一度クリックするとバッキング Bean から削除されます。

ただし、UI では、ボタンを 1 つだけクリックすると、すべてのボタンがトグルされているように見えます。たとえば、2009-2010 をクリックすると、次のように表示されます。

選択したすべて

4

1 に答える 1

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

binding 属性は、タイプUIComponentの Bean プロパティにバインドする必要があります。これは、フレームワークがバッキング Bean 内のコンポーネントへの参照を提供したり、バッキング Bean からインスタンスを提供したりする場合に使用されます)。詳細については、 JSF 1.2 仕様のセクション 3.1.5 を参照してください。


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

属性を動的にすることはidできません。JSF はclientIdを使用して、クライアントでの一意性を保証します(詳細については、こちらを参照してください)。


編集:

ただし、UI では、ボタンを 1 つだけクリックすると、すべてのボタンがトグルされているように見えます。

ice:panelSeries一部の繰り返しコントロール(dataTableなど)のように、すべての行のコンポーネントの状態を保存しないと推測しています。「行」ごとに 1 回エンコード/デコードされる場合でも、ボタン インスタンスは 1 つしかないことに注意してください。

私は ICEfaces を使用したことはありませんが、次のような Bean にバインドすることをお勧めします。

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>

したがって、リスト内の項目ごとに、すべてのバインディングが 1 つの状態 (SelectionBean インスタンス) に戻り、コンポーネント自体に非宣言状態を格納しようとはしません。

action私はできる限りoverを使用するようactionListenerにしています - JSF を POJO から遠ざけます。

于 2009-08-04T21:06:31.290 に答える