こちらを参考にして、CakePHP3でAJAXを使ったバリデーションに挑戦してみました。
前提
- フォームのフォーカスが外れた際に、validationを実行する
- フォーカスを得たときにメッセージをクリアする
- friendsofcakeのbootstrap-uiプラグインを使用している
CakePHP3でtwitter bootstrapを使う(導入編)
Javascript
以下のようなJavascriptファイルを設置します。
webroot/js/ajax-validate.js
(function($){
$.fn.validate = function(t) {
var elements = this;
elements.each(function(n, i) {
$(this).on('focus', function() {
var help_target;
if ($(this).prev().attr("class") == 'input-group-addon') {
help_target = $(this).parent();
} else {
help_target = $(this);
}
var error_target = $(this).parents(".form-group").get(0);
$(help_target).nextAll('p.help-block').remove();
$(error_target).removeClass('has-error');
});
$(this).on('blur', function() {
var help_target;
if ($(this).prev().attr("class") == 'input-group-addon') {
help_target = $(this).parent();
} else {
help_target = $(this);
}
var error_target = $(this).parents(".form-group").get(0);
var key = $(this).attr('name');
var check_data = {'key': key, 'value': $(this).val()};
$.ajax({
type: 'POST',
url: t.url,
data: check_data
}).done(function(data) {
if (data) {
data = JSON.parse(data);
for (key in data) {
error_message = data[key];
break;
}
$(help_target).after('<p class="help-block">' + error_message + '</p>');
$(error_target).addClass("has-error");
}
});
});
});
return this;
}
})(jQuery);
if ($(this).prev().attr("class") == 'input-group-addon') {
help_target = $(this).parent();
} else {
help_target = $(this);
}
の部分は、viewファイル内で、prependを指定した場合と指定しない場合で、DOM構造が変わるためこのような変な記述になっています。
prepend使わないのであれば、 help_target = $(this) だけで良いはずです。
Viewファイル
src/Template/Users/add.ctp
echo $this->Form->input('username', [
'prepend' => '<i class="fa fa-font fa-fw"></i>',
'class' => 'ajax-validate',
]);
echo $this->Form->input('password', [
'prepend' => '<i class="fa fa-key fa-fw"></i>',
'class' => 'ajax-validate',
]);
ajax-validateというクラスをつけておきます
src/Template/Users/add.ctp
echo $this->Html->script('/js/ajax-validate');
<script type="text/javascript">
$('.ajax-validate').validate({url: "/users/ajax_validate"});
</script>
ajax-validateクラスに設置したJavascriptファイルのメソッドをアサインします。
Controllerファイル
src/Controller/UsersController.php
public function ajax_validate()
{
if ($this->request->is('ajax')) {
$this->autoRender = false;
$key = $this->request->data['key'];
$data = [
$key => $this->request->data['value']
];
$user = $this->Users->newEntity($data);
if ($errors = $user->errors() and array_key_exists($key, $errors)) {
$this->response->body(json_encode($errors[$key]));
}
}
}
JSONを返すので、
$this->autoRender = false;
を指定します。