読者です 読者をやめる 読者になる 読者になる

Eclipse+JSF+JPAで作るアプリ(15)―Primefaces データテーブルの設定 後半(2) コンテキストメニュー

Primefacesのデータテーブルタグ(p:datatable)の設定を色々と変えて動作を確認を行うセッションの後半その2です。

のうち、コンテキストメニューの表示を行えるようにします。

コンテキストメニューはパネルメニューやメニューバー同様、とても簡単に作れます。
f:id:tshix:20150731222758p:plain
p:dialogを使った埋め込みダイアログ
f:id:tshix:20150731222809p:plain

コンテキストメニューの設定

表示したいデータテーブルのid(下記例では"userList")に対して、p:contextMenuタグのforアトリビュートで指定するだけです。
下記例では<p:contextMenu for="userList">です。

userlist.xml

	<p:dataTable id="userList" 

	</p:dataTable>

	<p:contextMenu for="userList">
		<p:menuitem value="パスワードの編集" 
			icon="ui-icon-pencil"
			update="dialog"
			oncomplete="PF('passwordDialog').show()">
			<f:setPropertyActionListener 
				value="#{editUserView.selectedUsers[0].password}" 
				target="#{editUserView.newPassword}"/>
		</p:menuitem>
	</p:contextMenu>
  • updateアトリビュートで、下記ダイアログを更新するように指定し、
  • oncompleteアトリビュートで、ダイアログをshowしています。
  • f:setPropertyActionListenerで、下記ダイアログのパスワードフィールドを初期化しています。

埋め込みダイアログの作成

パスワード表示メニューから、管理者にパスワードを入力させるためのダイアログを表示します。
PrimefacesのShowcaseに似たような例があります。

<h:form id="userListForm"></h:form>

<p:dialog id="dialog" header="パスワードの編集" widgetVar="passwordDialog"
	modal="true" showEffect="fold" hideEffect="explode" resizable="false"
	dynamic="true">
	<h:form id="dialogForm">
		<p:outputPanel id="passwordEdit" style="text-align:center;">
			<p:panelGrid columns="2">
				<f:facet name="header">
					<p:outputLabel
						value="#{editUserView.selectedUsers[0].name.concat('のパスワード変更')}" />
				</f:facet>
				<p:outputLabel value="パスワード" />
				<p:password value="#{editUserView.newPassword}" redisplay="true" />
				<p:outputLabel value="見えるパスワード" />
				<p:inputText value="#{editUserView.newPassword}" />
			</p:panelGrid>
			<p:commandButton value="OK" icon="ui-icon-check"
				action="#{editUserView.updatePassword}"
				oncomplete="PF('passwordDialog').hide()" />
			<p:commandButton value="キャンセル" icon="ui-icon-close"
				oncomplete="PF('passwordDialog').hide()" />
		</p:outputPanel>
	</h:form>
</p:dialog>

p:dialogタグでは

  • widgetVar="passwordDialog"が、PF('xxx').show(), PF('xxx').hide()で渡すIDになります。
  • modal="true"でモーダルダイアログになります。
  • dynamic="true"でフォームがロードされた際に遅延ロードされるようになります。

後はほかのフォームと同じです。注目したい点は

  • p:outputLabelタグのvalue="#{editUserView.selectedUsers[0].name.concat('のパスワード変更')}"で、EL式の文字列を連結しています。
  • p:passwordタグの redisplay="true" でパスワードの初期値を設定しています。(後述)
  • p:commandButtonタグのoncomplete="PF('passwordDialog').hide()"を呼ばないと当然ながらダイアログが消えません。

EditUserView.javaの変更点
特に大きな変更点はありません。

	@Getter @Setter 
	private String newPassword;
	…
	public String updatePassword()
	{
		if( selectedUsers == null || selectedUsers.isEmpty() )
			return "success";
		User user = selectedUsers.get(0);
		if( newPassword.equals(user.getPassword()))
			return "success";//同じなら更新しない。
		user.setPassword(newPassword);
		UserManager.updateUser(user);
		ViewUtil.AddMessage("パスワードの変更", user.getName()+"のパスワードを変更しました。");
		return "success";
	}

ダイアログの値のアップデート

p:menuitemで、update="dialog"を指定しなければ、値は更新されません。
また、はまった点として、ダイアログのコントロールにパスワードを使用していたため、editUserView.newPasswordの値が空に見え、ManagedBeanが更新されていないかのように振る舞っていました。inputSecretには、redisplayを付けない限り、クリアされるのを忘れていました。

ダイアログで表示しているnewPasswordの値のアップデート方法は、いくつか方法があります。

  1. actionListenerでnewPasswordを設定する方法。
  2. 本例のように、setPropertyActionListenerを使う方法。
  3. actionで更新してしまう方法。

1番目はjavaのコーディングが発生します。3番目は画面遷移を伴わないですから使用すべきではないです。
結果として、2番のsetPropertyActionListenerを使用して更新しています。

右クリックで行が選択されるが、削除ボタンが有効にならない。

次のajaxでイベントを拾ってあげます。

	<p:dataTable id="userList" 

		>
		<p:ajax event="contextMenu" 
			update=":userListForm:removeButton" /></p:dataTable>

さて、次はグリッド編集(cellEditorとrowEditorの使用方法)です。