フォーム全体を送信する前に画像を ajax アップロードしてプレビューする機能を備えたフォームで Primefaces を使用してページを作成しています。
これを達成するために、メインフォームの外側にダイアログを作成しました:
<p:dialog id="imageDlg" header="Load Image" modal="true"
widgetVar="imageUploadWidget">
<h:form id="imageForm" enctype="multipart/form-data">
<p:fileUpload mode="advanced" auto="true" sizeLimit="9999999"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/"
fileUploadListener="#{pageBean.imageUploadHandler}">
</p:fileUpload>
</h:form>
</p:dialog>
メインフォーム内にはp:graphicImage
、アップロードしたばかりの画像を表示するコンポーネントと、ダイアログを表示するボタンがあります。ページはビュー スコープ Bean ( PageBean
) によってサポートされていますが、値 Bean に渡すStreamedContent
にp:graphicImage
は、セッション スコープまたはアプリケーション スコープである必要があります (メソッドが複数回呼び出されるため)。ImageBean
そこで、この目的のためだけに2 つ目のアプリケーション スコープ Bean ( ) を作成しました。
<p:graphicImage value="#{imageBean.imageStreamedContent()}"/>
<p:commandButton value="Choose image" type="button"
onclick="imageUploadWidget.show();"/>
のコードImageBean
:
@ApplicationScoped
@ManagedBean
public class ImagesBean implements Serializable {
private byte[] image;
//getter & setter
public StreamedContent imageStreamedContent() {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
return new DefaultStreamedContent();
} else {
return new DefaultStreamedContent(new ByteArrayInputStream(getImage()));
}
}
}
次の部分ですfileUploadListener
。アイデアは単純です — PageBean
(フォーム送信時に後で保存するため) の対応するフィールドを設定し、 ImageBean
(部分的な更新後に表示するために) メインフォームの一部を更新します:
@ManagedBean
@ViewScoped
public class PageBean implements Serializable {
@ManagedProperty(value="#{imageBean}")
ImagesBean imagesBean;
...
public void imageUploadHandler(FileUploadEvent event) {
getImagesBean().setImage(event.getFile().getContents());
RequestContext.getCurrentInstance().update("form:tabPanel1");
}
ここで奇妙なことが起こります。メソッド内setImage()
ではすべて問題ありません - フィールドが設定され、ゲッターは正常に動作します。しかし、その後ページを更新すると、imageBean.getImage()
内部imageBean.imageStreamedContent()
は null を返します。
より正確 — setter が呼び出されなかったか、Bean の別のインスタンスで呼び出されたかのように、古い値を返します。String
別のフィールドでチェックしました。ImageBean
コンストラクターで初期化し、ハンドラーで別の値でセッターを呼び出し、メインフォームの一部を更新しました。同じこと: コンストラクターからの古い値。
Bean のライフサイクルまたはスコープ固有の何かが欠けていると思います。それとも、このタスクを実装するためのより簡単な方法がありますか?