[Grails]動的scaffoldに検索フォームを追加する

#概要
Grailsの便利な機能であるscaffold。
これは、プログラミングすること無く、データベースのデータを閲覧、作成、修正、削除することが出来るようになる機能です。
静的scaffoldであればGrailsによって作成されたファイルに自分で検索フォームを追加することが出来ます。
でもドメインが多くなってくると全てに毎回検索フォームを追加するのは面倒。。。
さらに動的scaffoldに至っては追加不可能です。
そこで登場するのが[filterpaneプラグイン](http://grails.org/plugin/filterpane)です。
こいつを利用することで、動的に検索フォームを出力することが出来るようになります。

#プラグインのインストール
何はともあれプラグインのインストール。

```grails-app/conf/BuildConfig.groovy
...省略...
plugins{
    ...省略...
    compile ":filterpane:2.4.5"
}

```

コレでGrailsの再起動（インタラクティブモードも一旦抜けたほうが良い）すればインストール完了。

#テンプレートの修正

で、動的scaffoldなので、当然表示されるHTMLとか全て動的に生成されるわけです。
そこで、テンプレートを修正してあげる必要が有ります。
以下のコマンドを実行してテンプレートをインストールします。
`grails install-templates`

##実際に修正
### 検索フォームを追加する。
`src/templates/scaffolding/index.gsp`にいくつかソースを追記します。
具体的には、filterpaneのjsとcssを読み込み、実際にfilterpaneが検索フォームを表示する部分を追記します。

```jsp:src/templates/scaffolding/index.gsp
	<head>
		<meta name="layout" content="main">
		<asset:javascript src="fp.js"/><!-- この行を追加 -->
		<asset:stylesheet src="fp.css"/><!-- この行を追加 -->
		<g:set var="entityName" value="\${message(code: '${domainClass.propertyName}.label', default: '${className}')}" />
		<title><g:message code="default.list.label" args="[entityName]" /></title>
	</head>
	<body>
	
        <!-- ここから追加 -->
        <!-- この箇所に、実際の検索用フォームが表示される -->
	<div class="pagination">
		<g:paginate total="\${${propertyName}Count ?: 0}" params="\${filterParams}" namespace="backend.scaffold"/>
		<filterpane:filterButton />
		<filterpane:filterPane domain="${domainClass.fullName}"    />
	</div>
        <!-- ここまで追加 -->
```


### 検索処理を実行するアクションの追加
テンプレートのコントローラに、以下のアクションメソッドを追加します。

```groovy:src/templates/scaffolding/Controller.groovy
    def filterPaneService
    def filter = {
        if(!params.max) params.max = 10
        render( view:'index',
                model:[ ${propertyName}List: filterPaneService.filter( params, ${className} ),
                        ${propertyName}Count: filterPaneService.count( params, ${className} ),
                                       filterParams: org.grails.plugin.filterpane.FilterPaneUtils.extractFilterParams(params),
                                       params:params 
                ]
        )
    }
```

###ネームスペースを使っている場合の追加処理

ネームスペースを使っている場合は、filterpaneが出力しているformにnamespaceを指定してあげる必要が有ります。

```jsp:target/work/plugins/filterpane-2.4.5/grails-app/views/_filterpane/_filterpane.gsp
    <form name="${fp.formName}" id="${fp.formName}" method="${fp.formMethod}" action="${createLink(action: fp.formAction, namespace:'backend.scaffold')} ">

```

これで準備完了です。
適当なドメインを作って動的scaffold用コントローラを用意してアクセスしてみましょう。
いつもと特に変わりのないscaffold画面が表示されるはずです。
でも、画面上部に**Filter**というリンクが現れいます。
コレをクリックすると実際の検索フォームが現れます。

![Cityリスト.png](https://qiita-image-store.s3.amazonaws.com/0/11059/32bed5c3-b00a-b3c5-0cd7-9fc89b7ca958.png)

残念ながら、`hasMany`や`belongsTo`を始め、別ドメインを保持しているプロパティに関しては検索フォームで項目が生成されないようです。
それでも、ちゃんと関連を張っているのであれば、親ドメインから検索もできるので、必要十分だと思います。




#参考
[http://grails.org/plugin/filterpane](http://grails.org/plugin/filterpane)

https://blog.uni-koeln.de/rrzk-knowhow/2012/03/14/add-filter-pane-to-your-customized-scaffolded-templates-for-list-pages/


#追記(2015/01/31)
上で 
>残念ながら、`hasMany`や`belongsTo`を始め、別ドメインを保持しているプロパティに関しては検索フォームで項目が生成されないようです。

と書きましたが、それらを扱う方法がちゃんと用意されていました。
近々その点もまとめて再度投稿予定です。