Magento + JQuery + Ajax - How do I reload just parts of my custom Module instead of the whole Block?

19,049

So I came up with a solution that works just awesome. I added another controller action and a model to do the Magento Interactions during my ajax calls. So let me show you how it's done, I hope somebody can profit from this sooner or later :)

My new Action:

public function updateAction ()
   {

      //Instantiate Product Model
      $productModel = Mage::getModel('doorconfig/product');

      //Get Updated Values from the Model
      $currentProduct = $productModel->getProduct($_POST);
      $currentProductId = $currentProduct->getId();
      $currentProductUrl = $currentProduct->getProductUrl();
      $currentPrice = $productModel->getPrice($currentProductId);
      $currentType = $this->getRequest()->getPost('doorconfig_type');
      $currentSize = $this->getRequest()->getPost('doorconfig_size');
      $currentProductBaseImgUrl = $productModel->getDoorBaseImgUrl($currentType,$currentSize);

      //Populate Resultarray
      $result = array("currentProductId"=>$currentProductId,"currentPrice"=>$currentPrice,"currentProductUrl"=>$currentProductUrl,"currentProductBaseImgUrl"=>$currentProductBaseImgUrl);

      //Encode Result in JSON
      $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));

      return $result;
   }

My model just got most of the business logic from my block, so nothing special to point out about that.

And finally the updated Ajax section which now triggers my new controller action, receives the result as a JSON encode and changes the values in the DOM:

<script type="text/javascript">

   var $price = "";
   var $baseImgUrl = "";
   var $productUrl = "";
   var $productId = "";
   var $f = $j("#attributeform");
    var $formData;
    var $currentStoreUrl = "<?php echo $currentStoreUrl ?>";

   function ajaxUpdate()
   {

      $j.ajax({
         url: "/doorconfig/index/update",
         type: "POST",
         data: $formData,
         dataType: "json",
         success: function(data) 
                {
                  $productId = data.currentProductId;
                  $price = data.currentPrice;
                  $baseImgUrl = data.currentProductBaseImgUrl;
                  $productUrl = data.currentProductUrl;
                     $j("#result").text($price);

                     $j("#addtocart").attr('href',  $currentStoreUrl + "checkout/cart/add?product=" + $productId + "&qty=1");
                     $j("#productimg").attr('src', $baseImgUrl);

                     console.log(data);

                   },
            error: function(error)
                  {
                     console.log("Error:");
                     console.log(error);
                     alert("ERROR");
                  }
        });
    };

   $j(document).ready(function() 
   {

      $j("#result").text('<?php echo $defaultProductPrice; ?>');
      $j("#addtocart").attr('href', '<?php  echo $currentStoreUrl . "checkout/cart/add?product=" . $defaultProductId . "&qty=1" ?>');
      $j("#moreinfo").attr('href', '<?php echo $defaultProductUrl; ?>');
      $j("#productimg").attr('src', '<?php echo $defaultProductImgUrl; ?>');
      $j("#attributeform")[0].reset();

      $j("form[name=attributeform]").change(function () 
      {

         $formData = $f.serialize();
         ajaxUpdate();
      })
   });   

</script>

If you need any further explanation or wanna improve something please comment :)

Share:
19,049
ericstumper
Author by

ericstumper

Updated on June 05, 2022

Comments

  • ericstumper
    ericstumper almost 2 years

    I was just recently given the task to create a simple Product configurator for our Magento Template in 5 days, where you can choose some attributes and it calculates the price for you, fades over a new image and changes the add to cart button to the new product.

    Before this I had no experience in PHP or JQuery and just some basics in Magento (never done a custom module before.) My only programming Background is OOP Games in Action Script 3.

    So far my code works somehow. I have some variables that I can change on click of some radio buttons and the variables are updated via the ajax method. As URL my block index method is called which does just load and render my layout. After I add the returned HTML (which is my whole block) to the parent of my outermost div in my block. It works but I can't seem to find a way to animate the changes and it seems kind of slow if the ajax rebuilds the whole block each time the user just changes one option.

    Is there a more elegant way to just reload the changed parts, smoothly animate the changes and make my block remember the inputs that were made?

    Here are the source files for download: http://www.roflxd.de/doorconfig.zip

    If you need to see the site itself, please message me :)

    Thanks in advance!

    My Block phtml:

        <?php 
    
                    $type = 'Simple';
                    $color = 'FFFFFF';
                    $size = '2500x1800';
    
                    if (isset($_POST['color'])) {
                        $color = "#" . $_POST['color'];
                    }
    
                    if (isset($_POST['type'])) {
                        $type = $_POST['type'];
                    }
    
                    if (isset($_POST['size'])) {
                        $size = $_POST['size'];
                    }
    
                    $currentStoreUrl = Mage::getBaseUrl();
    
                    $currentProduct = $this->getProduct($type,$color,$size);
    
                    $currentId = $currentProduct->getId();
    
                    $currentUrl = $currentProduct->getProductUrl();         
    
                    $currentPrice = $this->getPrice($currentId);
    
                    $currentImgUrl = $this->getDoorBaseImgUrl($type, $size);
    
    ?>
    
    <div id="door_wrapper" class="">
        <div id="door_left_wrapper" class="mj-grid48">
    
            <form id="testform">
    
                <div id="door_colors">
    
                    <label id="FFFFFF">White<input type="radio" name="toggle" value="FFFFFF"></label>
                    <label id="000000">Black<input type="radio" name="toggle" value="000000"></label>
                    <label id="736D6C">Grey<input type="radio" name="toggle" value="736D6C"></label>
    
                </div>
    
                <div id="door_model" >
    
                    <?php print_r($_POST); ?>
    
                    <?php echo $type;?>
                    <?php echo $color;?>
                    <?php echo $size;?>
    
                    <br>
    
                    <?php echo $currentImgUrl;?>
                </div>
    
                <div id="door_size">
    
                    <select name="doorsizes">
                    </select>
    
                </div>
    
                <?php if ($currentProduct->isSaleable()): ?>
                    <button type="button">
                        <a href="<?php echo $currentStoreUrl . "checkout/cart/add?product=" . $currentId . "&qty=1";?>">
                            Test
                        </a>
                    </button>
                <?php else: ?>
                    <button disabled>Out of Stock</button>
                <?php endif;?>
    
            </form>
    
        </div>
    
        <div id="door_right_wrapper" class="mj-grid48">
    
            <div id="door_img">
                <img src="<?php echo $currentImgUrl;?>">
            </div>
    
            <div id="result"></div>
        </div>
    
    </div>
    
    <script type="text/javascript">
    
        var $col = "000000";
        var $type = "Advanced";
        var $size = "3050x2150";
    
        function ajaxUpdate()
        {         
            $j.ajax({
                url: "/doorconfig/ajax/index",
                type: "POST",
                data: {color : $col, type : $type, size : $size },
                context: $j('#door_wrapper').parent(),
                success: function(data) 
                         {
                            $j(this).html(data).$(this).fadeIn(slow);
                         }
            });
        };
    
        $j(document).ready(function() 
                           {    
                              $j("input[name=toggle]:radio").change(function ()
                                                                    {
                                                                        ajaxUpdate();
                                                                    })
                           });   
    
    </script>
    

    My Block php:

        <?php
    class Geeklab_DoorConfig_Block_Doorconfig extends Mage_Core_Block_Template
    {
    
        public function getProduct($type,$color,$size)
        {
    
            //Get Product Collection
            $collection = Mage::getModel('catalog/product')->getCollection();
    
            //Select needed Attributes
            $collection->addAttributeToSelect('doorconfig_enable'); 
            $collection->addAttributeToSelect('doorconfig_color');
            $collection->addAttributeToSelect('doorconfig_size');
            $collection->addAttributeToSelect('doorconfig_type');
    
            //Filter for Selected Product
            $collection->addFieldToFilter('doorconfig_enable',
                    array(
                            'eq' => Mage::getResourceModel('catalog/product')
                                        ->getAttribute('doorconfig_enable')
                                        ->getSource()
                                        ->getOptionId('Yes')
                         )
            );
    
            $collection->addFieldToFilter('doorconfig_color',
                    array(
                            'eq' => Mage::getResourceModel('catalog/product')
                                        ->getAttribute('doorconfig_color')
                                        ->getSource()
                                        ->getOptionId($color)
                         )
            );
    
            $collection->addFieldToFilter('doorconfig_size',
                    array(
                            'eq' => Mage::getResourceModel('catalog/product')
                                        ->getAttribute('doorconfig_size')
                                        ->getSource()
                                        ->getOptionId($size)
                         )
            );
    
            $collection->addFieldToFilter('doorconfig_type',
                    array(
                            'eq' => Mage::getResourceModel('catalog/product')
                                        ->getAttribute('doorconfig_type')
                                        ->getSource()
                                        ->getOptionId($type)
                         )
            );
    
            $product = $collection->getFirstItem();
    
            return $product;
        }
    
        public function getPrice($id)
        {
            $product = Mage::getModel('catalog/product')->load($id);
            $_taxHelper  = new Mage_Tax_Helper_Data;
            $finalprice = $_taxHelper->getPrice($product, $product->getFinalPrice(), true);
            $finalprice .= $this->getCurrency();
            return $finalprice;
        }
    
        public function getCurrency()
        {
            return Mage::app()->getLocale()->currency(Mage::app()->getStore()->getCurrentCurrencyCode())->getSymbol();
        }
    
        public function getDoorImageDir()
        {
            return Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA) . 'wysiwyg/geeklab/doorconfig/';
        }
    
        public function getDoorBaseImgUrl($type, $size)
        {
            return $this->getDoorImageDir() . strtolower($size) . '_' . str_replace("\040", "\137", strtolower($type)) . '.png';
        }
    
        public function getDoorColorImgUrl($color, $size)
        {
            return $this->getDoorImageDir() . strtolower($size) . '_' . strtolower($color) . '.png';
        }
    }
    
    ?>
    

    And my AjaxController.php

        <?php
    
    class Geeklab_DoorConfig_AjaxController extends Mage_Core_Controller_Front_Action
    {
       public function indexAction ()
       {
            $this->loadLayout();
            $this->renderLayout();
       }
    
    }
    ?>
    
  • Admin
    Admin over 10 years
    could you show me what your xml files look like for this. Thanks :)