【问题标题】:Magento + JQuery + Ajax - How do I reload just parts of my custom Module instead of the whole Block?Magento + JQuery + Ajax - 如何仅重新加载自定义模块的一部分而不是整个块?
【发布时间】:2013-06-04 14:10:25
【问题描述】:

我最近刚刚接到任务,在 5 天内为我们的 Magento 模板创建一个简单的产品配置器,您可以在其中选择一些属性,它会为您计算价格、淡入新图像并更改添加到购物车按钮到新产品。

在此之前,我没有 PHP 或 JQuery 方面的经验,只了解 Magento 的一些基础知识(以前从未做过自定义模块。)我唯一的编程背景是动作脚本 3 中的 OOP 游戏。

到目前为止,我的代码以某种方式工作。我有一些变量可以通过单击一些单选按钮来更改,并且这些变量通过 ajax 方法进行更新。作为 URL,我的块索引方法被调用,它只是加载和呈现我的布局。在我将返回的 HTML(这是我的整个块)添加到我的块中最外层 div 的父级之后。它可以工作,但我似乎无法找到一种方法来为更改设置动画,如果每次用户只更改一个选项时 ajax 重建整个块,它似乎有点慢。

有没有更优雅的方法来重新加载更改的部分、平滑地为更改设置动画并让我的模块记住所做的输入?

这里有源文件供下载:http://www.roflxd.de/doorconfig.zip

如果您需要查看网站本身,请给我留言 :)

提前致谢!

我的块 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>

我的块 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';
    }
}

?>

还有我的 AjaxController.php

    <?php

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

}
?>

【问题讨论】:

  • 我正在逐个弄清楚理论。当前的行为非常有意义,因为我调用了在任何 ajax 事件上呈现布局的控制器,每次都重新加载 html。所以我需要第二个控制器动作或模型之类的东西,然后它会回答我的 ajax 调用并给我新的产品值。通过 jQuery 更改 DOM 并继续侦听更改后。 phtml 只会从 Magento 获取初始数据并初始化 configurator 的 select 和 color 字段。但问题仍然存在:我需要什么,模型、新控制器动作还是新控制器?
  • 在另一个控制器操作中收集数据是一种好习惯吗?我可以从我的 Block.php 那里访问这些功能吗?这么多问题,请给我提示以正确的方式解决这个问题:)
  • 我不得不在 Mage 中做同样的事情。一个团队成员编写了模块,我连接了 ajax。我使用 jQuery 发布到他在控制器中编写的操作方法。 Alan Storm's 站点是获取一些关于编写模块的好信息的好地方。希望这有助于为您指明正确的方向。
  • 所以您还通过 2 种操作方法来实现它,一种用于构建布局,另一种用于在 ajax 请求上发回新产品数据?这意味着我应该可以在那里使用我的块方法 ^^ 你是使用 JSON 作为返回格式还是其他格式?我已经阅读了很多 Alan Storms 的文章,这让我更容易获得基础知识 :)
  • 阅读此QUESTION 我认为可以在我的新控制器操作中进行变量设置,但随后阅读 Alan Storms 的答案,这似乎不是一个好习惯。所以我想到我需要第二个控制器 Action 来实例化数据操作的模型。没有找到任何指南,没有使用资源模型进行数据库访问:/我只想从 Magento 读取简单数据并将其作为 JSON 发送回我的块。

标签: php ajax magento jquery


【解决方案1】:

所以我想出了一个非常棒的解决方案。我在 ajax 调用期间添加了另一个控制器操作和一个模型来执行 Magento 交互。所以让我告诉你它是如何完成的,我希望有人迟早可以从中获利:)

我的新动作:

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

我的模型刚刚从我的块中获取了大部分业务逻辑,所以没有什么特别需要指出的。

最后是更新的 Ajax 部分,它现在触发我的新控制器操作,接收 JSON 编码的结果并更改 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>

如果您需要任何进一步的解释或想要改进某些内容,请发表评论:)

【讨论】:

  • 你能告诉我你的 xml 文件是什么样子的吗?谢谢:)
猜你喜欢
  • 2014-05-22
  • 2023-01-11
  • 1970-01-01
  • 2019-12-27
  • 1970-01-01
  • 2014-02-19
  • 2017-04-02
  • 1970-01-01
相关资源
最近更新 更多