2

次のように、文字列の形式で通貨のリストを使用します。

<p:selectOneMenu id="currency"
                 value="#{currencyRateBean.currency}"
                 onchange="changeCurrency([{name: 'currency', value: this.value}]);">

    <f:selectItems var="row"
                   value="#{currencyBean.currencies}"
                   itemLabel="#{row}"
                   itemValue="#{row}"/>
</p:selectOneMenu>

に沿って<p:remoteCommand>

<p:remoteCommand ignoreAutoUpdate="true"
                 name="changeCurrency"
                 partialSubmit="true"
                 process="@this"
                 update="@none"
                 action="#{currency.currencyAction}"/>

通貨値を設定するマネージド Bean が、上記を介して<p:remoteCommand>JavaScript 関数にパラメーターとして渡されます。

@Named
@RequestScoped
public class Currency {

    @Inject
    @HttpParam
    private String currency;

    @Inject
    private CurrencyRateBean currencyRateBean;

    public Currency() {}

    public String currencyAction() throws MalformedURLException, IOException {

        try (Scanner scanner = new Scanner(new URL("http://www.exchangerate-api.com/INR/" + currency + "/1?k=FQRxs-xT2tk-NExQj").openConnection().getInputStream(), "UTF-8");) {
            currencyRateBean.setCurrencyRate(scanner.nextBigDecimal());
            currencyRateBean.setCurrency(currency);
        } catch (UnknownHostException | ConnectException e) {}

        return FacesContext.getCurrentInstance().getViewRoot().getViewId() + "?faces-redirect=true&includeViewParams=true";
    }
}

提供された通貨の値は、上記CurrencyRateBeanのアクション メソッド内から別のセッション スコープのマネージド Bean に設定され、最終的に現在の値にcurrencyAction()基づいてリダイレクトを行います。viewIdincludeViewParams=true


#{currencyRateBean.currencies}ここで、これまで文字列のリストであった複合オブジェクトのリストを持つように変更された場合、話は変わります。

次のシナリオは機能しませんが、includeViewParams=trueこれは重要です。

<p:selectOneMenu value="#{currencyRateBean.currencyHolder}">

    <f:selectItems var="row" value="#{currencyBean.currencies}"
                   itemLabel="#{row.currency}"
                   itemValue="#{row}"/>

    <p:ajax event="change"
            listener="#{currency.currencyAction}"
            partialSubmit="true"
            process="@this"
            update="@none"/>
</p:selectOneMenu>
public void currencyAction()  throws IOException {
    // ...
    FacesContext facesContext = FacesContext.getCurrentInstance();
    String viewId = facesContext.getViewRoot().getViewId();

    ExternalContext externalContext = facesContext.getExternalContext();
    externalContext.redirect(externalContext.getRequestContextPath() + viewId + "?includeViewParams=true");
}

includeViewParams=true装飾用にのみ追加されています。うまくいきません。

listenerinは、 of<p:ajax>のようにナビゲーション ケースの結果に基づいてリダイレクトを行うことができないため、とにかく使用する必要があります。action<p|h:commandXxx>ExternalContext#redirect()

<p:remoteCommand>の完了時に使用できます<p:ajax>が、これにはサーバーへの不必要な 2 回の往復が含まれます。最初に関連付けられたマネージド Bean に通貨値を設定し、次にリダイレクトを行います。

与えられた例でリダイレクトを行う方法はincludeViewParams=true?

4

1 に答える 1

3

のようfaces-redirect=trueに、includeViewParams=trueに渡す「プレーンな」URL ではなく、ナビゲーションの結果でのみ機能しますExternalContext#redirect()

を使用しNavigationHandler#handleNavigation()ます。

FacesContext context = FacesContext.getCurrentInstance();
String outcome = viewId + "?includeViewParams=true";
context.getApplication().getNavigationHandler().handleNavigation(context, null, outcome);

または、OmniFacesを使用します。

Faces.navigate(viewId + "?includeViewParams=true");

ExternalContext#redirect()疑わしい代替手段は、すべてのビューパラメーターを自分で収集し、それらをクエリ文字列に変換して、とにかく使用できるようにすることです。これは、OmniFaces を使用すると簡単です。

Faces.redirect(viewId + "?" + Servlets.toQueryString(Faces.getViewParameterMap()));
于 2016-03-08T20:07:37.377 に答える