2012-05-10 9 views
3

たinvoke私は検証を結合してuserIdPlayerに変換しようとするこのf:viewParamを持っているとき、私は予期しない結果を得ました。F:viewParamコンバータとViewScoped例外うちでは、第二のAJAXリクエスト

私は偉大3つのリンク(ハリー、トム・ピーター)、コンバータの作業をクリックするとマイConverterは、この

@FacesConverter(value="pConverter") 
public class PConverter implements Converter { 
private static final List<Player> playerList; 
static{ 
    playerList = new ArrayList<Player>();   
    playerList.add(new Player(1, "Harry")); 
    playerList.add(new Player(2, "Tom")); 
    playerList.add(new Player(3, "Peter")); 
} 

@Override 
public Object getAsObject(FacesContext fc, UIComponent uic, String value) { 
    if(value == null || !value.matches("\\d+")){ 
     return null; 
    } 
    long id = Long.parseLong(value); 
    for(Player p : playerList){ 
     if(p.getId() == id){ 
      return p; 
     } 
    } 
    throw new ConverterException(new FacesMessage("Unknown userId: " + value)); 

} 

@Override 
public String getAsString(FacesContext fc, UIComponent uic, Object value) { 
    if(!(value instanceof Player) || value == null){ 
     return null; 
    } 
    return String.valueOf(((Player)value).getId()); 
} 
} 

ように見える

<f:metadata> 
    <f:viewParam name="userId" value="#{myBean.selectedPlayer}" converter="pConverter" 
     converterMessage="Bad Request. Unknown User" required="true" 
     requiredMessage="Bad Request. Please use a link from within the system" /> 

</f:metadata> 
<h:body> 
    <p:messages id="msgs"/>   
    <h:form> 
     <ul> 
      <li><a href="index2.xhtml?userId=1">Harry</a></li> 
      <li><a href="index2.xhtml?userId=2">Tom</a></li> 
      <li><a href="index2.xhtml?userId=3">Peter</a></li> 
     </ul>    
    </h:form> 
    <h:form> 
     <h:panelGrid columns="2" rendered="#{not empty myBean.selectedPlayer}"> 

      <h:outputText value="Id: #{myBean.selectedPlayer.id}"/> 

      <h:outputText value="Name: #{myBean.selectedPlayer.name}"/> 

     </h:panelGrid> 
    </h:form> 
    <h:form id="testForm"> 
     <h:inputText value="#{myBean.text}"/> 
     <p:commandButton value="Switch" update=":msgs testForm"/> 
     <h:outputText value="#{myBean.text}" rendered="#{not empty myBean.text}"/> 
    </h:form>  
</h:body> 

。それはidを変換してplayerを私のマネージドBeanに戻します。次に、テキストボックスに何かを入力して、Switchをクリックすると、最初に正常に動作し、入力した内容がボタンの隣に表示されますが、入力した内容が変更され、Switchを再度クリックすると、エラーメッセージが表示されますBad Request. Please use a link from within the systemf:viewParamの場合はrequiredのエラーメッセージが表示されます。私がf:viewParamを取り出した場合、すべて正常に動作します。驚いたことに、私がf:viewParamからo:viewParam(OmniFaces)に切り替えると、うまく動作します。

答えて

4

これは、<f:viewParam>がすべての単一HTTP要求で実行され、ポストバックでも実行されるためです。これは、リンクでそのパラメータを正確に渡しているため、普通のGETリンクの場合はうまく動作します。 POSTフォームの場合は、そのパラメーターをボタンに渡していないため、ケースでは失敗します。したがって、要求パラメータマップにnullとなり、requiredバリデーターが起動し、この検証エラーが発生します。

POSTフォームでも<f:viewParam required="true">を満足させるには、コマンドボタン/リンクで初期要求パラメータを<f:param>に保持する必要があります。ビューと組み合わせて使用​​するように設計され

<p:commandButton value="Switch" update=":msgs testForm"> 
    <f:param name="userId" value="#{param.userId}" /> 
</p:commandButton> 

OmniFaces <o:viewParam>は、豆をスコープ、isRequired()ゲッター(source code here)に追加のチェックがあります。だから

@Override 
public boolean isRequired() { 
    // The request parameter get lost on postbacks, however it's already present in the view scoped bean. 
    // So we can safely skip the required validation on postbacks. 
    return !FacesContext.getCurrentInstance().isPostback() && super.isRequired(); 
} 

が、これはrequiredバリをスキップポストバックごとに(また、ステートレスな性質のため、ポストバックごとにモデル値を設定することもスキップします)。そのため、検証エラーは表示されず、適切なモデル値(すべてのポストバックではリセットされません)が残っています。

+0

ありがとうございました。 Omnifacesはかなり素晴らしいです、BalusC。私はあなたのブログで、 'o:viewParam'に関する1つの質問を持っていますが、ajaxリクエストが呼び出されるたびに全部が' Converter'を呼び出さないように言いましたが、常にメソッド 'getAsString()'の中に入っているようです。だから私はこの動作が正しいかどうか疑問に思います。 'getAsObject'はモデル値を設定するものなので、' getAsObject'を呼び出さないと大きな改善ができません。それに感謝します。 –

+1

'getAsString()'は、オブジェクトを文字列に変換する必要があるときに呼び出されます(生成されたHTMLに表示されます)。しかし、それはすでにそのプロパティの文字列値になっているので、かなり安い仕事でなければなりません。その時点ですでにオブジェクトを手にしているので、高価なDBジョブは必要ありません。 – BalusC

+0

ありがとうございました。 –