Updating multiple dom elements using jQuery Taconite

This article has moved to this location.


In my previous article, i’ve shown how to update dom element using ajax in symfony form. Another question now arise, how if you want to update more than one dom elements? In this article i’ll show you how to do that using jquery taconite plugin. What is jquery taconite plugin? jquery taconite plugin is a plugin that allows you to easily make multiple DOM updates using the results of a single AJAX call. It processes an XML command document that contain instructions for updating the DOM (stolen from jquery taconite website πŸ˜‰ ). For more details about jquery taconite, you can read here.
I’ll take my previous article as example, but now it’s have three choice widgets.
When user change the value of choice1, the options in choice2 will change according to selected value of choice1 and choice2 will update the options in choice3 as soon as it’s options is changed.

Let start explore the code..

  1. Create the primary form.
    class myForm extends sfForm
    {
       public function setup()
       {
    	$items = array('' => '-- Your Choice --', '1' => 'Item 1', '2' => 'Item 2');
    	$this->setWidgets(array(
    	  'choice_1' => new sfWidgetFormChoice(array('choices' => $items)),
    	  'choice_2' => new sfWidgetFormChoice(array('choices' => array(''=>'Waiting from selection from category 1'))),
    	  'choice_3' => new sfWidgetFormChoice(array('choices' => array(''=>'Waiting from selection from category 2'))),
    	));
    	$this->setValidators(array(
     	  'choice_1' => new sfValidatorChoice(array('choices' => array_keys($items))),
    	));
    	$this->widgetSchema->setNameFormat('form1[%s]');
            $this->errorSchema = new sfValidatorErrorSchema($this->validatorSchema);
       }
    }
    
  2. Create another form that extends the form you want to ajaxify (in this post is myForm) and remove unused field(s).
    class myAjaxSelectForm extends myForm
    {
       public function configure()
       {
    	unset($this['choice_1']);
            $choice1 = sfContext::getInstance()->getRequest()->getPostParameter('choice_1_id');
    	$choices2 = $this->buildChoice2($choice1);
    	$this->widgetSchema['choice_2'] = new sfWidgetFormChoice(array('choices' => $choices2));
    	$this->validatorSchema['choice_2'] = new sfValidatorChoice(array('choices' => array_keys($choices2)));
    
    	$selected_value = null;
    	if (count($choices2) > 0)
    	{
      	     $keys = array_keys($choices2);
    	     $selected_value = $keys[0];
    	}
    	$choices3 = $this->buildChoices3($selected_value);
    	$this->widgetSchema['choice_3'] = new sfWidgetFormChoice(array('choices' => $choices3));
    	$this->validatorSchema['choice_3'] = new sfValidatorChoice(array('choices' => array_keys($choices3)));
       }
    
       protected function buildChoices3($choice_2)
       {
    	$choices = array();
    	if ($choice_2)
    	{
      	    switch ($choice_2)
    	   {
    		case 1:
    	 	    $choices = array('1' => 'Item 7', '2' => 'Item 8');
    		    break;
    		case 2:
    		    $choices = array('3' => 'Item 9', '4' => 'Item 10');
    		    break;
    		case 3:
    		    $choices = array('5' => 'Item 11', '6' => 'Item 12');
    		    break;
    		case 4:
    		    $choices = array('7' => 'Item 13', '8' => 'Item 14');
    		    break;
    	    }
    	}
    	return $choices;
       }
    
       protected function buildChoice2($choice_1)
       {
     	$choices = array();
    	switch ($choice_1)
    	{
    	    case 1:
    	       //sub items of item 1 = array(Item 3, Item 4)
    		$choices = array('1' => 'Item 3', '2' => 'Item 4');
    		break;
    	    case 2:
    		//sub items of item 2 = array(Item 5, Item 6)
    		$choices = array('3' => 'Item 5', '4' => 'Item 6');
    		break;
    	 }
    	return $choices;
        }
    }
    
  3. In your actions.class.php, add the action to show your main form.
    public function executeTest_select(sfWebRequest $request)
    {
         $this->form = new myForm();
    }
    

    and create the corrensponding template..

    <!-- test_selectSuccess -->
    <?php use_helper('jQuery') ?>
    <?php use_javascript('jquery.taconite.js', 'last') ?>
    <form action="<?php echo url_for('generic/index') ?>" >
    <fieldset>
    <legend>Test Ajax</legend>
       <table cellspacing="0">
     	<tbody>
           <tr>
    	   <td>Category 1</td>
    	   <td><?php echo $form['choice_1'] ?></td>
           </tr>
           <tr>
    	  <td>Category 2</td><td><div id="choice2"><?php echo $form['choice_2'] ?></div></td>
           </tr>
           <tr>
    	   <td>Category 3</td><td><div id="choice3"><?php echo $form['choice_3'] ?></div></td>
           </tr>
        </tbody>
      </table>
    </fieldset>
    </form>
    <?php echo jq_javascript_tag(
    "
    jQuery(document).ready(function() {
      jQuery('#form1_choice_1').change(update_multipe_choices = function(){
        jQuery.ajax({type:'POST', data:{
          choice_1_id: jQuery(this).val()},
          beforeSend:function(XMLHttpRequest){},
          success:function(XMLHttpRequest, textStatus){},
          url:'".url_for('generic/ajax_select')."'});
      });
    });
    "
    ) ?>
    
  4. In your actions.class.php add an ajax action
    public function executeAjax_select(sfWebRequest $request)
    {
    	$this->forward404Unless($request->isXmlHttpRequest());
    	$this->setLayout(false);
            $this->getResponse()->setContentType("text/xml");
    	$this->form = new myAjaxSelectForm();
    }
    

    then create the template (ajax_selectSuccess.php)

    <taconite>
    <replaceContent select="#choice2">
       <?php echo $form['choice_2'] ?>
    </replaceContent>
    <replaceContent select="#choice3">
       <?php echo $form['choice_3'] ?>
    </replaceContent>
    </taconite>
    

This is far from perfect.. i know, you must have a better solution than this, so.. let share with me..
Have fun with symfony… πŸ˜‰

3 responses to “Updating multiple dom elements using jQuery Taconite

  1. jp May 18, 2010 at 3:43 am

    symfony b4 1.1? or 1.2+

  2. jp May 18, 2010 at 4:40 am

    its alright got it going on sf1.2.. nice πŸ˜‰

  3. Skyblue March 31, 2011 at 10:26 am

    I’m new in symfony. In what location will you create the first two codes and what specific file name.

Leave a comment