После прочтения статьи я решил написать декоратор который будет прикреплять jquery код для получения данных из формы и отправки их на сервер.
Своим опытом спешу поделится с хабрасообществом.
То как создавать декораторы и о формах в модели замечательно описывается в статье ссылку на которую я привёл выше, так что заострять на этом внимание я не буду.
Итак нам нужно чтобы получилось нето следуещее:
Решение элементарно:
у нас есть 2 метода
getJSCode() — генерирует jquery код для формы в зависимости от того какие параметры существуют в форме, а именно нам нужны action и method этой формы, а так же id кнопки submit и id самой формы для получения из неё параметров.
Ещё нам понадобиться div для того чтобы возвращать в него ответ сервера.
Получаем экземпляр класса формы из него получаем элемент submit далее составляем код в который добавлен div для того чтобы записывать в него ответы от сервера.
В jquery для обработчика click возвращаем false иначе при нажатии на кнопку пользователь будет попадать на страницу с заданным action.
Осталось реализовать стандартный метод render который предоставляет нам Zend_Form_Decorator_Abstract, там всё достаточно просто взависимости от опций декоратора возвращаем jquery код на нужном месте.
Затем нам нужен декоратор для элемента формы он будет дописывать див к кэлементу в который будем писать сообщение о том что данные из этой формы не прошли валидацию.
здесь всё аналагично предыдущему декоратору только вместо JSкода мы вставяем код с нашим дивом у которого id =«error_<имя элемента формы>»
Нам нужно будет создать сообщение о том что валидация не увенчалась успехом
Здесь мы немного расширяем класс Zend_Form дописывая туда пути для валидаторов декораторов и фильтров а так же устанавливая файл с переведёнными ошибками на русский язык.
Метод printErrorMessages() выводит для каждого элемента код который вставляет в нужный див сообщение о ошибке, если таковая имееться.
Нам понадобится форма описанная например вот так:
это простая форма добавления комметария, здесь помимо всего прочего мы устанавливаем декоратор AjaxError для нужных нам полей
$login->addDecorator('AjaxErrors');
Ну и последнее это использование.
У нас есть 2 события первое это в котором выводится сама форма, а во второе мы будет отсылать данные.
Создаём форму привязываем к ней декоратор и отправляем в вид, в виде стоит незабыть подключить jquery.
Здесь мы снова создаём нашу форму, затем проверяем каков запрос если он передан Ajax`ом значит JS у пользователя в браузере включён, тогда двигаемся дальше, иначе выкидываем сообщение с советом включить JS. Затем если произошел POST и значения в форме валидны делаем что-то например заносим сообщение в бд.
Многие могут сказать что это куча ненужного кода, будет уменьшаться производительность скриптов, но на практике это очень сильно экономит время, нам не приходится много раз переписывать один и тот же код, нам нужно будет только создать форму и прекрепить к ней декоратор и ajax готов :)
Надеюсь что это пригодится кому то и избавит от рутины.
Своим опытом спешу поделится с хабрасообществом.
То как создавать декораторы и о формах в модели замечательно описывается в статье ссылку на которую я привёл выше, так что заострять на этом внимание я не буду.
Итак нам нужно чтобы получилось нето следуещее:
<from ...> <input ...> <div id="error_..."> Сюда будем выводить сообщение о том что поле не прошло валидацию </div> </form> <div id =""> Сюда мы будем выводить ответ от сервера <div> <script> Здесь код для обработки формы </script>
Решение элементарно:
class App_Form_Decorator_Ajax extends Zend_Form_Decorator_Abstract { public function getJSCode() { $form = $this->getElement(); $button = $form->getElement('submit'); $jsCode=' <div id ="check'.$form->getAttrib('id').'"></div> <script> $("#'.$button->getAttrib('id').'").click(function () { data = $("#'.$form->getAttrib('id').'").serialize(); $.ajax({ type: "'.$form->getMethod().'", url: "'.$form->getAction().'", data: data, success: function(msg){ $("#check'.$form->getAttrib('id').'").html(msg) } }); return false; }); </script> '; return $jsCode; } public function render($content) { $element = $this->getElement(); if (null === $element->getView()){ return $content; } $placement = $this->getPlacement(); switch ($placement) { case 'APPEND': return $content.$this->getJSCode(); case 'PREPEND': return $this->getJSCode().$content; case null: default: return $content.$this->getJSCode(); } } }
у нас есть 2 метода
getJSCode() — генерирует jquery код для формы в зависимости от того какие параметры существуют в форме, а именно нам нужны action и method этой формы, а так же id кнопки submit и id самой формы для получения из неё параметров.
Ещё нам понадобиться div для того чтобы возвращать в него ответ сервера.
Получаем экземпляр класса формы из него получаем элемент submit далее составляем код в который добавлен div для того чтобы записывать в него ответы от сервера.
В jquery для обработчика click возвращаем false иначе при нажатии на кнопку пользователь будет попадать на страницу с заданным action.
Осталось реализовать стандартный метод render который предоставляет нам Zend_Form_Decorator_Abstract, там всё достаточно просто взависимости от опций декоратора возвращаем jquery код на нужном месте.
Затем нам нужен декоратор для элемента формы он будет дописывать див к кэлементу в который будем писать сообщение о том что данные из этой формы не прошли валидацию.
class App_Form_Decorator_AjaxErrors extends Zend_Form_Decorator_Abstract { public function _getHtmlCode() { $element = $this->getElement(); $HtmlCode=' <div id="error_' . $element->getName() . '"></div> '; return $HtmlCode; } public function render($content) { $element = $this->getElement(); if (!$element instanceof Zend_Form_Element) { return $content; } if (null === $element->getView()) { return $content; } $placement = $this->getPlacement(); switch ($placement) { case 'APPEND': return $content.$this->_getHtmlCode(); case 'PREPEND': return $this->_getHtmlCode().$content; case null: default: return $content.$this->_getHtmlCode(); } } }
здесь всё аналагично предыдущему декоратору только вместо JSкода мы вставяем код с нашим дивом у которого id =«error_<имя элемента формы>»
Нам нужно будет создать сообщение о том что валидация не увенчалась успехом
class App_Form extends Zend_Form { public function init() { // Вызов родительского метода parent::init(); // Создаем объект переводчика, он нам необходим для перевода сообщений об ошибках. // В качестве адаптера используется php массив $translator = new Zend_Translate('array', './application/translate/errors.php'); // Задаем объект переводчика для формы $this->setTranslator($translator); /* Задаем префиксы для самописных элементов, валидаторов, фильтров и декораторов. Благодаря этому Zend_Form будет знать где искать наши самописные элементы */ $this->addElementPrefixPath('App_Validate', 'App/Validate/', 'validate'); $this->addElementPrefixPath('App_Filter', 'App/Filter/', 'filter'); $this->addElementPrefixPath('App_Form_Decorator', 'App/Form/Decorator/', 'decorator'); } public function printErrorMessages() { echo '<script>'; foreach ($this->getElements() as $element){ $errors = ''; foreach ($element->getMessages() as $error){ $errors.= $error . "<br>"; } echo '$("#error_' . $element->getName() . '").html("' . $errors . '");'; } echo '</script>'; } }
Здесь мы немного расширяем класс Zend_Form дописывая туда пути для валидаторов декораторов и фильтров а так же устанавливая файл с переведёнными ошибками на русский язык.
Метод printErrorMessages() выводит для каждого элемента код который вставляет в нужный див сообщение о ошибке, если таковая имееться.
Нам понадобится форма описанная например вот так:
class Form_Comment extends App_Form { public $action = '/index/add/'; public function init() { parent::init(); $helper = new Zend_View_Helper_Url(); $this->setMethod('POST'); $this->setAction('/index/add/'); $this->setAttrib('id','commentform'); $login = new Zend_Form_Element_Text( 'login', array( 'label'=> 'Имя', 'required' => true, 'filters' => array('StringTrim') )); $login->addDecorator('AjaxErrors'); $this->addElement($login); $message = new Zend_Form_Element_Textarea( 'message', array( 'label'=> 'Cooбщение', 'required' => true )); $message->addDecorator('AjaxErrors'); $this->addElement($message); $submit = new Zend_Form_Element_Submit('submit', array( 'label' => 'Добавить комментарий', 'id'=>'qwer' )); $this->addElement($submit); } }
это простая форма добавления комметария, здесь помимо всего прочего мы устанавливаем декоратор AjaxError для нужных нам полей
$login->addDecorator('AjaxErrors');
Ну и последнее это использование.
У нас есть 2 события первое это в котором выводится сама форма, а во второе мы будет отсылать данные.
function indexAction() { $commentForm = new Form_Comment(); $this->view->commentForm = $commentForm; $commentForm->addDecorator(new App_Form_Decorator_Ajax()); }
Создаём форму привязываем к ней декоратор и отправляем в вид, в виде стоит незабыть подключить jquery.
function addAction() { $commentForm = new Form_Comment(); if($this->getRequest()->isXmlHttpRequest()){ if ($this->_request->isPost()) { if ($commentForm->isValid($this->_getAllParams())) { echo $commentForm->getValue('login')."<br>"; echo $commentForm->getValue('message'); }else { $commentForm->printErrorMessages(); } } } else { echo "Включите пожалуйста javascript в вашем браузере"; } }
Здесь мы снова создаём нашу форму, затем проверяем каков запрос если он передан Ajax`ом значит JS у пользователя в браузере включён, тогда двигаемся дальше, иначе выкидываем сообщение с советом включить JS. Затем если произошел POST и значения в форме валидны делаем что-то например заносим сообщение в бд.
Многие могут сказать что это куча ненужного кода, будет уменьшаться производительность скриптов, но на практике это очень сильно экономит время, нам не приходится много раз переписывать один и тот же код, нам нужно будет только создать форму и прекрепить к ней декоратор и ajax готов :)
Надеюсь что это пригодится кому то и избавит от рутины.