Вообщем нужно было сделать так что бы форма не только проходила валидацию по ajax, но и в случае успешной валидации происходила запись в бд без перезагрузки страници.
Пришлось править файлы самого фреймворка.
Форма комментария рендерится на странице поста
в форме есть такой код
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'comment-form',
'enableAjaxValidation'=>true,
'method'=>'post',
'action'=>$this->createAbsoluteUrl('/comment/create'),
'clientOptions'=>array(
'validateOnSubmit'=>true,
'onSubmit'=>'js:function(data){$(\'#comment-button\').before(data.content);}'
)
)); ?>
изменения которые произвел в jquery.yiiactiveform.js (отмечено //!!!)
(хм видно встроенная подсветка как то испортила некоторіе названия переменных и пр.)
....
$.each(settings.attributes, function(i,attribute){
settings.attributes[i] = $.extend({
validationDelay : settings.validationDelay,
validateOnChange : settings.validateOnChange,
validateOnType : settings.validateOnType,
onSubmit : settings.onSubmit, //!!!
hideErrorMessage : settings.hideErrorMessage,
....
});
ajaxValidate(function(data) {
$.each(settings.attributes, function(){
if (this.status == 3) {
updateInput(this, data.errors); //!!!
}
});
});
....
if (settings.validateOnSubmit) {
var validated = false;
$form.submit(function(){
if (validated)
return true;
ajaxValidate(function(data){
var hasError = false;
$.each(settings.attributes, function(i, attribute){
hasError = updateInput(attribute, data.errors) || hasError; //!!!
});
updateSummary(data.errors); //!!!
if(!hasError) {
validated = true;
if(settings.onSubmit){
settings.onSubmit(data);
}
else{
$form.submit();
}
validated = false;
}
});
return false;
});
}
....
$.fn.yiiactiveform.defaults = {
ajaxVar: 'ajax',
validationUrl: undefined,
validationDelay: 100,
validateOnSubmit : false,
validateOnChange : true,
validateOnType : false,
onSubmit : false, //!!!
hideErrorMessage : false,
....
изменения в CActiveForm
....
public static function validate($models, $loadInput=true, &$isValidated = null, &$rawResult = null)
{
$result=array();
if(!is_array($models))
$models=array($models);
foreach($models as $model)
{
if($loadInput && isset($_POST[get_class($model)]))
$model->attributes=$_POST[get_class($model)];
$model->validate();
foreach($model->getErrors() as $attribute=>$errors)
$result[CHtml::activeId($model,$attribute)]=$errors;
}
if($isValidated !== null)
{
$isValidated = empty($result);
}
$result = array('errors'=>$result);
if($rawResult !== null)
{
$rawResult = $result;
}
return function_exists('json_encode') ? json_encode($result) : CJSON::encode($result);
}
....
в контроллере
....
public function filters() {
return array(
'accessControl', // perform access control for CRUD operations
'ajaxOnly + create',
);
}
....
public function actionCreate() {
$model=new Comment;
$isValidated = false;
$result = array();
$json = CActiveForm::validate($model, true, $isValidated, $result);
if($isValidated) {
if(isset($_POST['Comment'])) {
$model->attributes=$_POST['Comment'];
if($model->save()){
$result['content'] = $this->renderPartial('_view',array('data'=>$model), true);
$result['success'] = true;
echo function_exists('json_encode') ? json_encode($result) : CJSON::encode($result);
}
else{
$result['success'] = false;
echo function_exists('json_encode') ? json_encode($result) : CJSON::encode($result);
}
}
}
else{
echo $json;
}
}
....
как видите стандратная валидация осталась нетронутой, я в том смысле что не придется переделывать конроллеры которые были написаны ранее.
в случае удачной валидации создасться комментарий и его отрендеренное представление вернется в форму и будет вызвана функции onSubmit которая добавить комментарий в конец очереди.
Можете попробовать добавить комментарий на любой странице http://creative-territory.net/.
Есть небольшая проблема при первом сабмите говорит что контент пустой, при повторном все нормально работает. Есть предположение что это из-за CKEditor’а. Возможно придется заменить onSubmit на onAfterSubmitValidate и добавить еще onBeforeSubmitValidate, что бы как то перенести данные из CKEditor’а в соотвествующую <textarea>. Или вообще отказаться от этой затеи.
Вообщем нужны ваши комментарии, критика и прочее.
Может стоит просить что бы что то подобное добавили в официальную версию. Или кто как вообще реализовывал подобное.
Спасибо