📜 ⬆️ ⬇️

Decorator for processing forms Ajaxʻom

After reading the article, I decided to write a decorator that will attach the jquery code to get the data from the form and send it to the server.
I hasten to share my experience with the community.

How to create decorators and forms in the model is described in the article the link to which I cited above, so I will not focus on this.
So we need to get neto next:

 <from ...>
 <input ...>
 <div id = "error _...">
 Here we will display a message stating that the field failed validation.
 </ div>
 </ form>
 <div id = "">
 Here we will display a response from the server
 <div>
 <script>
 Here is the form processing code.
 </ script>



The solution is elementary:
 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 ();
		 }
	 }
 }


we have 2 methods
getJSCode () - generates jquery code for the form depending on which parameters exist in the form, namely, we need the action and method of this form, as well as the id of the submit button and the id of the form itself to get the parameters from it.
We also need a div in order to return the server response to it.
We get an instance of the form class from it, we get the submit element, then we compose a code in which a div is added in order to write responses from the server to it.
In jquery, for the click handler, we return false; otherwise, when the user clicks a button, the user will go to the page with the specified action.
It remains to implement the standard render method which gives us Zend_Form_Decorator_Abstract, everything is quite simple, depending on the options of the decorator, we return the jquery code in the right place.
')
Then we need a decorator for a form element; it will add a div to the element in which we will write a message stating that the data from this form has not been validated.
 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 ();
		 }
	 }
 }



here everything is analogous to the previous decorator, but instead of the JS code, we insert the code with our div at which id = “error_ <name of the form element>”

We will need to create a message stating that the validation failed

 class App_Form extends Zend_Form 
 {  
     public function init ()
     {
         // Call the parent method
         parent :: init ();
        
         // Create a translator object, we need it to translate error messages.
         // As an adapter php array is used
         $ translator = new Zend_Translate ('array', './application/translate/errors.php');
        
         // Set the translator object for the form
         $ this-> setTranslator ($ translator);
        
         / * Set prefixes for samopisny elements, validators, filters and decorators.
            Thanks to this Zend_Form will know where to look for our hand-written elements * /
        $ 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>';
       }
 }



Here we are slightly expanding the Zend_Form class by adding there paths for validators of decorators and filters as well as setting the file with the errors translated into Russian.
The printErrorMessages () method displays for each element a code that inserts an error message into the desired div, if any.

We will need the form described for example like this:

 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' => 'Name',
		 'required' => true
		 'filters' => array ('StringTrim')
	 ))
	 $ login-> addDecorator ('AjaxErrors');
	 $ this-> addElement ($ login);
	 $ message = new Zend_Form_Element_Textarea (
	 'message',
	 array (
		 'label' => 'Cooperative',
		 'required' => true
	 ))
	 $ message-> addDecorator ('AjaxErrors');
	 $ this-> addElement ($ message);	
             $ submit = new Zend_Form_Element_Submit ('submit', array (
             'label' => 'Add a comment',
             'id' => 'qwer'
         ))
         $ this-> addElement ($ submit);
     }
 }



This is a simple form for adding comments. Here, among other things, we set the AjaxError decorator for the fields we need.
$ login-> addDecorator ('AjaxErrors');

Well, the last is the use.

We have 2 events, the first is in which the form itself is displayed, and in the second we will send data.

 function indexAction ()
     {
         $ commentForm = new Form_Comment ();
         $ this-> view-> commentForm = $ commentForm;
         $ commentForm-> addDecorator (new App_Form_Decorator_Ajax ());
     }



Create a form, we attach a decorator to it and send it to the view, in the form it is worth remembering to connect 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 "Please enable javascript in your browser";
     }
 }



Here we again create our form, then check what the request is if it is transmitted by Ajax, which means JS is turned on in the browser, then we move on, otherwise we throw out a message with the advice to enable JS. Then, if POST has occurred and the values ​​in the form are valid, we do something, for example, write the message in the database.

Many may say that this is a bunch of unnecessary code, script performance will decrease, but in practice it saves time, we don’t have to rewrite the same code many times, we only need to create a form and decorator to it and ajax is ready: )
I hope that this is useful to someone and get rid of the routine.

Source: https://habr.com/ru/post/52675/


All Articles