何がしたかったか
セレクトボックスで選択した値によって、ビューに出力されるフォームを変えたかった。
実装
まず、もとのフォームは以下のようにFormhelperを使って書く。このとき、ajaxでポストしたいデータはselectフォームの[name='test']のバリューのみ。Form->createでは'url'オプションをfalseにすることにより、デフォルトのコントローラー/アクション設定を無効化できる。ここで、あとでajaxでformを識別できるように、idを絶対につけとく。
/view.ctp
<?php echo $this->Form->create(null, [
'class' => 'form-inline',
'id' => 'test-form',
'url' => false
]); ?>
<?php echo $this->Form->select('test', $options, [
'class'=> 'form-control'
]); ?>
<?php echo $this->Form->button('選択', [
'class' => 'form-control',
]); ?>
<?php echo $this->Form->end(); ?>
// 新しく追加したいフォームをロードできるhtmlエレメント(divとかtbodyとか)を用意しとく。
<div id="new-form">
</div>
次に、このフォームからのデータをcontrollerへポストするjsコード。
jqueryに用意されてるloadコマンドでcontroller側でrenderされたビューを選択したdivに表示してくれる。
ajax.js
$(function() {
$('#test-form').on('submit', function(){
// ここでポストされたtestのバリューを取得。
var test = $('[name="test"]').val();
// ここでajaxでcontroller/actionにtestをpost。
// renderされたビューをnew-formにロードする。
$('#new-form').load("/controller/test", {
test : test
});
});
});
コントローラー/アクションは以下のような感じ。
/controller
public function test() {
if($this->request->is('post')) {
// ここで、postされたselectフォームの「test」に対応する値を取得。
$test = $this->request->getData('test');
// $testを使って色々計算して、$varを導く。
// この$varを次に出力するフォームに投げたい。
$var = ...
$this->set(compact('var'));
$this->render('Element/test_element', 'ajax');
}
}
出力されるフォームはelementに書いといて、必要な変数を設定したあと、それをrenderすればよい。
例えば、renderしたいelementは以下のようにフォームだけを書いとく。
/Elements/test_element.ctp
<?php if ($var) {?>
<div>
// $varを使って新たなフォームのビューをつくる
</div>
<?php } ?>
以上のような構成で、ある一つのフォームで選択した値によって、また新たなフォームを出力できるようになる。