Magento 2 AJAX ile HTML oluşturma


12

Magento 2 AJAX ile HTML oluşturmak için en iyi yolu bulmaya çalışın.

Yol 1: Denetleyiciyi düzen olmadan kullanma

Dosya Foo/Bar/Controller/Popin/Content.php

<?php

namespace Foo\Bar\Controller\Popin;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;

/**
 * Class Content
 */
class Content extends Action
{

    /**
     * Content constructor.
     *
     * @param Context $context
     */
    public function __construct(
        Context $context
    ) {
        parent::__construct($context);
    }

    /**
     *
     */
    public function execute()
    {
        /** @var \Magento\Framework\View\Layout $layout */
        $layout = $this->_view->getLayout();

        /** @var \Foo\Bar\Block\Popin\Content $block */
        $block = $layout->createBlock(\Foo\Bar\Block\Popin\Content::class);
        $block->setTemplate('Foo_Bar::popin/content.phtml');

        $this->getResponse()->setBody($block->toHtml());
    }
}   

Yol 2: Denetleyiciyi özel düzen ile kullanma

Dosya Foo/Bar/Controller/Popin/Content.php

<?php

namespace Foo\Bar\Controller\Popin;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;

/**
 * Class Content
 */
class Content extends Action
{

    /**
     * Content constructor.
     *
     * @param Context $context
     */
    public function __construct(
        Context $context
    ) {
        parent::__construct($context);
    }

    /**
     *
     */
    public function execute()
    {
        $this->_view->loadLayout();
        $this->_view->renderLayout();
    }
}    

Dosya Foo/Bar/view/frontend/page_layout/ajax-empty.xml

<?xml version="1.0"?>

<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_layout.xsd">
    <container name="root"/>
</layout>

Dosya Foo/Bar/view/frontend/layout/foo_bar_popin_content.xml

<?xml version="1.0"?>

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="ajax-empty" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="root">
            <block class="Foo\Bar\Block\Popin\Content" name="foo_bar_popin_content" template="Foo_Bar::popin/content.phtml" cacheable="false"/>
        </referenceContainer>
    </body>
</page>

IMO'nun en iyi uygulaması , mantığı Denetleyiciden ayırdığı için Yol 2 gibi görünüyor .
Ama ile sorun Way 2 olmasıdır <body>ve <head>birlikte CSS/ JSo sadece benim blok şablonu ile tam temizlenmiş HTML olmayacak şekilde üretilir.

  • Özel düzeni yanlış şekilde mi kullanıyorum?
  • Is Way 1 iyi uygulama olarak kabul edilir?
  • Bunu yapmanın başka yolları var mı?

Yanıtlar:


18

Ben de yol 2 gitmek istiyorum ve aslında, aslında kafa, vücut, css ve benzeri olmadan AJAX üzerinden "saf" HTML oluşturabilirsiniz.

İşin püf noktası:

  • kumandanıza cevap vermek \Magento\Framework\View\Result\Layoutyerine türden bir Yanıt başlatmasını söyleyin\Magento\Framework\View\Result\Page
  • <layout...>...</layout>yerine kök düğümü olan bir düzen XML dosyası kullanın<page...>...</page>

İşte çok basit bir uygulama.

Kontrol eden, denetleyici

<?php    
namespace Namespace\Module\Controller\Index;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\ResultFactory;

class Index extends Action
{
    /**
     * Dispatch request
     *
     * @return \Magento\Framework\Controller\ResultInterface|ResponseInterface
     * @throws \Magento\Framework\Exception\NotFoundException
     */
    public function execute()
    {
        return $this->resultFactory->create(ResultFactory::TYPE_LAYOUT);
    }
}

Tasarım

<?xml version="1.0"?>
<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd">
    <container name="root">
        <block class="Namespace\Module\Block\Some\Block" name="namespace_module.some_block" />
    </container>
</layout>

Github Örneği

Bu örnek modüle bakın: https://github.com/herveguetin/Herve_AjaxLayout_M2

Bu modül bunu üretir:

resim açıklamasını buraya girin


Tüm düzeni yüklemek istersem (Birkaç kapsayıcı, blok vb. İçeren XML)? create -> toHtml ve json aracılığıyla ajax'a gönderilsin mi?
mattkrupnik

5

Kutunun dışında Magento, AJAX aracılığıyla HTML oluşturmak için bu yöntemlerden hiçbirini kullanmaz.

Gördüğüm kadarıyla, böyle bir şey yapılması gerektiğinde, JSON sonucu taşımak için kullanılır.

Örnek Magento/Checkout/Controller/Cart/Add:

$this->getResponse()->representJson(
    $this->_objectManager->get('Magento\Framework\Json\Helper\Data')->jsonEncode($result)
);

Daha sonra Magento 2, ön uçtaki verileri işlemek ve güncellenmesi gereken belirli blokları güncellemek için bölümler adında yeni bir mekanizma kullanır, bu Soru-Cevap bölümündeki bölümler hakkında daha fazla bilgi edinebilirsiniz: https://magento.stackexchange.com/a/ 143381/2380

Cevabımın ikinci kısmı ile ilgili EDIT: Max tarafından yorumda belirtildiği gibi, bölümler sadece müşteriye özel verilerle kullanılır ve her AJAX çağrısı yerine bu işlevselliği kullanmak doğru çözüm değildir.


Evet ayrıca sonucu taşımak için JSON kullanıyorum ama sorularım için sınıfları basitleştiriyorum;) Ama bu bölüm özelliğinin farkında değilim, istediğimi yapmanın doğru yolu gibi görünüyor. Bi 'bakacağım. Başka bir yanıt varsa bekleyeceğim, aksi takdirde cevabınızı doğrulayacağım. Teşekkürler !
Matthéo Geoffray

2
Ham html verileri yerine Json yanıtı kullanmayı kabul ediyorum. Ama cevabınızın ikinci kısmı tam doğru değil. Yalnızca müşteriye özel veriler için ve her Ajax çağrısı yerine bu işlevselliği kullanan müşteri bölümlerinin iyi bir fikir olmadığını unutmayın.
Max

2
@ Matthéo evet, anladım :) Cevabımı düzeltmek için Raphael'e yaptığım yorum, çünkü cevabın ikinci kısmı diğer kullanıcılar tarafından yanlış anlaşılabilir.
Max

1
@MaxStsepantsevich bunu tespit ettiğiniz için teşekkürler, cevabımı söylediklerinizi yansıtacak şekilde düzenledim
Raphael, Dijital Piyanizm'de

1
Geri bildirimlerinizi kullanarak bir yanıt ekledim. Yardımın için ikinize teşekkürler.
Matthéo Geoffray

3

Örneğimde kullanamıyorum sectionsçünkü değil customer datave bir PUT/ POSTeylemden sonra değil ama Raphael at Digital Pianismcevap kullanarak Magento'nun bölümleri nasıl oluşturduğunu anladım.

cartBölüm örneğini alırsak \Magento\Customer\CustomerData\SectionPool::getSectionDataByNames, bölümlerden veri alma yöntemini kullanır. Bu bizi \Magento\Checkout\CustomerData\Cart::getSectionDatabölümün alanlarını içeren tek bir diziye yönlendirir.$this->layout->createBlock('Magento\Catalog\Block\ShortcutButtons')->toHtml()

Buna bağlı olarak, son Controller sınıfı:

<?php

namespace Foo\Bar\Controller\Popin;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Data\Form\FormKey\Validator;
use Psr\Log\LoggerInterface;

/**
 * Class Content
 */
class Content extends Action
{

    /**
     * @var LoggerInterface $logger
     */
    private $logger;
    /**
     * @var Validator $formKeyValidator
     */
    private $formKeyValidator;
    /**
     * @var JsonFactory $resultJsonFactory
     */
    private $resultJsonFactory;

    /**
     * Content constructor.
     *
     * @param Context $context
     * @param LoggerInterface $logger
     * @param Validator $formKeyValidator
     * @param JsonFactory $resultJsonFactory
     */
    public function __construct(
        Context $context,
        LoggerInterface $logger,
        Validator $formKeyValidator,
        JsonFactory $resultJsonFactory
    ) {
        $this->logger            = $logger;
        $this->formKeyValidator  = $formKeyValidator;
        $this->resultJsonFactory = $resultJsonFactory;
        parent::__construct($context);
    }

    /**
     *
     */
    public function execute()
    {
        if (!$this->formKeyValidator->validate($this->getRequest())) {
            return $this->resultRedirectFactory->create()->setPath('checkout/cart/');
        }

        /** @var \Magento\Framework\Controller\Result\Json $resultJson */
        $resultJson = $this->resultJsonFactory->create();

        try {
            /** @var \Magento\Framework\View\Layout $layout */
            $layout = $this->_view->getLayout();
            /** @var \Foo\Bar\Block\Popin\Content $block */
            $block = $layout->createBlock(\Foo\Bar\Block\Popin\Content::class);
            /** @var array $response */
            $response = [
                'content' => $block->toHtml(),
            ];
        } catch (\Exception $exception) {
            $resultJson->setStatusHeader(
                \Zend\Http\Response::STATUS_CODE_400,
                \Zend\Http\AbstractMessage::VERSION_11,
                'Bad Request'
            );
            /** @var array $response */
            $response = [
                'message' => __('An error occurred')
            ];
            $this->logger->critical($exception);
        }

        return $resultJson->setData($response);
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.