Magento + JQuery + Ajax - Wie lade ich nur Teile meines benutzerdefinierten Moduls anstelle des gesamten Blocks neu?


7

Ich habe erst kürzlich die Aufgabe erhalten, in 5 Tagen einen einfachen Produktkonfigurator für unsere Magento-Vorlage zu erstellen, in dem Sie einige Attribute auswählen und den Preis für Sie berechnen, ein neues Bild überblenden und die Schaltfläche zum Hinzufügen zum Warenkorb in das neue ändern können Produkt.

Vorher hatte ich keine Erfahrung mit PHP oder JQuery und nur einige Grundlagen in Magento (noch nie ein benutzerdefiniertes Modul erstellt). Mein einziger Programmierhintergrund sind OOP-Spiele in Action Script 3.

Bisher funktioniert mein Code irgendwie. Ich habe einige Variablen, die ich durch Klicken auf einige Optionsfelder ändern kann, und die Variablen werden über die Ajax-Methode aktualisiert. Als URL wird meine Blockindexmethode aufgerufen, die nur mein Layout lädt und rendert. Nachdem ich den zurückgegebenen HTML-Code (der mein ganzer Block ist) zum übergeordneten Element meines äußersten Divs in meinem Block hinzugefügt habe. Es funktioniert, aber ich kann anscheinend keinen Weg finden, die Änderungen zu animieren, und es scheint etwas langsam zu sein, wenn der Ajax den gesamten Block jedes Mal neu erstellt, wenn der Benutzer nur eine Option ändert.

Gibt es eine elegantere Möglichkeit, die geänderten Teile einfach neu zu laden, die Änderungen reibungslos zu animieren und meinen Block an die Änderungen in meinen Eingaben zu erinnern?

Hier sind alle Dateien zum Download: http://www.roflxd.de/doorconfig.zip

Wenn Sie Zugriff auf die Website selbst benötigen, um zu sehen, wie sie derzeit aussieht, senden Sie mir bitte eine Nachricht :)

Danke im Voraus!

Mein 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>

Mein 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';
    }
}

?>

Und meine AjaxController.php

    <?php

class Geeklab_DoorConfig_AjaxController extends Mage_Core_Controller_Front_Action
{
   public function indexAction ()
   {
        $this->loadLayout();
        $this->renderLayout();
   }

}
?>

Ich finde die Theorie Stück für Stück heraus. Das aktuelle Verhalten ist absolut sinnvoll, da ich meinen Controller aufrufe, der das Layout bei jedem Ajax-Ereignis rendert. Das HTML wird jedes Mal neu geladen. Ich brauche also so etwas wie eine zweite Controller-Aktion oder ein zweites Controller-Modell, das dann meine Ajax-Anrufe beantwortet und mir die neuen Produktwerte gibt. Nachdem das DOM über jQuery geändert wurde und weiterhin auf Änderungen wartet. Das HTML würde nur die Anfangsdaten von Magento erhalten und die Auswahl- und Farbfelder für den Konfigurator initialisieren. Aber immer noch die Frage: Was brauche ich, Modell, neue Controller-Aktion oder neue Controller?
Ericstumper

Ist es empfehlenswert, die Daten in einer anderen Controller-Aktion zu erfassen? Habe ich dort Zugriff auf die Funktionen von meiner Block.php? So viele Fragen, bitte geben Sie mir einen Hinweis, um dies auf die richtige Weise zu lösen :)
Ericstumper

Antworten:


2

Also habe ich eine Lösung gefunden, die einfach fantastisch funktioniert. Ich habe eine weitere Controller-Aktion und ein Modell hinzugefügt, um die Magento-Interaktionen während meiner Ajax-Aufrufe durchzuführen. Also lass mich dir zeigen, wie es geht, ich hoffe jemand kann früher oder später davon profitieren :)

Meine neue Aktion:

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;
   }

Mein Modell hat gerade den größten Teil der Geschäftslogik aus meinem Block erhalten, daher gibt es nichts Besonderes, worauf ich hinweisen könnte.

Und schließlich empfängt der aktualisierte Ajax-Abschnitt, der jetzt meine neue Controller-Aktion auslöst, das Ergebnis als JSON-Codierung und ändert die Werte im 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>

Wenn Sie weitere Erklärungen benötigen oder etwas verbessern möchten, kommentieren Sie bitte :)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.