Grailsで家計簿--第6章「FujiからItemCodeのデータも入力」--

前へ 次へ

6.1やっているのは「はじめてのGrails」とおんなじです

ItemCodeにまだ登録してない商品コード・商品名のペアがあったら、いちいちItemCodeの入力画面に切り替えなくても、Fujiの入力画面から登録できるようにするんですが、実はココは「はじめてのGrails」と内容が全く同じです。だから出し惜しみするってわけじゃないんですけどあんな必死こいてやっと書いたのをまた書くのはもぉーたりくてヤなので、すみませんがサラっとコード例のみ紹介させていただきます。10年くらいして「昔そんなものも書いたことがあったわい」と懐かしく思い出せるようになったら詳しい説明を追加するかも知れません。

6.2入力した商品コードは登録されているか

Fujiのcreate.jspを編集して、テキストフィールドに商品コードを入力したときに、そのコードがItemCodeに登録済みであれば商品名がその場で表示されるように書きます。これはGrailsの組み込みAjaxを利用します。

FujiのCreateページの変更

1.Grailsの組み込みAjaxを使うには、ファイルprototype.jsを参照するように<head>タグ内に書いておきます。
<g:javascript library="prototype" />
2.商品コードを入力するテキストフィールド(第4章でワレワレが作った)と同じ行に、検索ボタンを配置します。これをクリックすると、その商品コードから商品名を検索するという想定です。

検索ボタンの記述には、フォームの中のパラメータを他のアクションに送る「submitToRemoteタグ」を使います。

「同じ行」ですから、ひとつの<tr>タグの中の別の<td>タグとして書き入れます。

<td valign="top" class="name">
	<label for="itemcode"><g:message code="fuji.itemcodedata.label" default="Itemcode" /></label>
	<g:textField name="itemcode"/>
</td>
<td>
	<g:submitToRemote url="[controller:'itemCode', action:'confirmNew']" update="showit" value="Search"/>
</td>
これで、
Searchと書かれたボタンを押したら、ItemCodeControllerのアクションconfirmNewにパラメータが送られて、結果はshowitというidのついた<div>タグに表示される
という指定ができます。この中で、アクションconfirmNewとshowitというidはまだ「名前を言ってみただけぇー」で、定義はこれから書かなければなりません。

3.メソッドのほうはItemCodeController.groovyを開かないといけませんから、まず「showitというidのついた<div>タグ」のほうを書きましょう。 書く場所は、「商品コードを入れるテキストフィールドとSearchボタン」の行の、すぐ下の行です。 そして、この行には、商品名が見つからなかった場合に新規商品名を入力するテキストフィールドも一緒に置くことにします。

<tr class="prop">
	<td class="name"><div id="showit"></td>
	<td valign="top" class="name">
		<label for="itemcodename">
			<g:message code="fuji.itemcodename.new.label" default="New Itemname (Optional)" />
		</label>
	</td>
	<td valign="top" class="value ${hasErrors(bean: fujiInstance, field: 'itemcodedata.itemname', 'errors')}">
		<g:textField name="itemname"/>
	</td>
</tr>
スタイル「class」の指定とかhasErrorsメソッドとかは、元のコードのサルマネです。

変更の確認

これ、見た目どうなるかだけ確認しておきましょう。アクションconfirmNewは何も定義しておかないとたぶんコンパイルエラーになるでしょうから、ItemCodeController.groovyを編集して、書くだけ書いておきます。
def confirmNew={
	render "It works!"
}
「Search」ボタンをクリックすると「It works!という文字が表示されます。これで、インターフェイスはできました。

アクションconfirmNewの内容

アクションconfirmNewは、商品名があるかないかを示すだけですから簡単です。
def confirmNew={

	def ans="A new code"//見つからなかった場合のメッセージを初期値に
	
	def itemcodeInstance=ItemCode.findByItemcode(params.itemcode)
	if(itemcodeInstance){
		//見つかったら改めてメッセージを変更
		ans="Registered:${itemcodeInstance.itemname}"
	}

	//元からある「メッセージ」の外観を拝借
	render {div(class:"message", ans)}		

}
既に登録されているコードの場合、Searchボタンをクリックすると商品名が表示されますから、「よし商品コードだけでいいぞォー」とわかります。登録されていなければ「A new code」と表示されますから、「商品コードもテキストボックスに入力しなきゃいけないな」とわかるわけです。

でも、まだ「わかる」というだけで、実際の処理は定義していません。これからします。

6.3新しい商品名が送られてきたら、新しいオブジェクトを作成

編集するのはFujiController.groovyのsaveメソッドです。ここはすでに、以下のような作業をするように書き換えてあるんでした。
  1. とにかく空っぽのFujiオブジェクトを新規作成
  2. 送られてきた商品コードの値を持つItemCodeオブジェクトを検索
  3. そのItemCodeオブジェクトを、新規作成したFujiオブジェクトのプロパティitemcodeにつけてやる
  4. 完成したFujiオブジェクトを保存
ここをさらに書き換えます。
  1. とにかく空っぽのFujiオブジェクトを新規作成
  2. 商品名が送られてきたら、送られてきた商品コードと商品名をもとに新しいItemCodeオブジェクトを作成
  3. この新しいItemCodeオブジェクトを保存
  4. 商品名が送られてこなかったら、送られてきた商品コードの値を持つItemCodeオブジェクトを検索
  5. とにかく得られたItemCodeオブジェクトを、新規作成したFujiオブジェクトのプロパティitemcodeにつけてやる
  6. 完成したFujiオブジェクトを保存
コードに直すと以下のようになります。
 def fujiInstance = new Fuji()
	if(params.itemname!=null && params.itemname != ""){
			fujiInstance.itemcodedata=new ItemCode(itemcode:params.itemcode, itemname:params.itemname).save()
	}
		else{
				fujiInstance.itemcodedata=ItemCode.findByItemcode(params.itemcode)
	}
		bindData(fujiInstance,params,[exclude:"itemcodedata"])
これでもうItemCode小アプリケーションはほとんど表に出なくてもいい感じになりました。でも、Fujiからの入力の結果が何か変になった場合の修正インターフェイスとしては重宝します。 最後に、「同じ日付の買い物データを続けて入力したい」場合を考えましょう。次へ