Magento 2 में AJAX के साथ HTML कैसे रेंडर करें


12

मैं Magento 2 में AJAX के माध्यम से HTML रेंडर करने का सबसे अच्छा तरीका खोजने की कोशिश करता हूं।

तरीका 1: बिना लेआउट के कंट्रोलर का उपयोग करना

फ़ाइल 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());
    }
}   

रास्ता 2: कस्टम लेआउट के साथ नियंत्रक का उपयोग करना

फ़ाइल 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();
    }
}    

फ़ाइल 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>

फ़ाइल 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 सबसे अच्छा अभ्यास तरीका 2 लगता है क्योंकि यह नियंत्रक से तर्क को अलग करता है।
लेकिन साथ इस मुद्दे रास्ता 2 कि है <body>और <head>साथ CSS/ JSउत्पन्न कर रहे हैं तो यह उस में केवल मेरे ब्लॉक टेम्पलेट के साथ एक पूर्ण साफ एचटीएमएल नहीं है।

  • क्या मैं गलत तरीके से कस्टम लेआउट का उपयोग कर रहा हूं?
  • क्या रास्ता 1 को एक अच्छा अभ्यास माना जाता है?
  • क्या ऐसा करने के कोई और तरीके हैं?

जवाबों:


18

मैं भी रास्ते 2 और जाएगा, वास्तव में, आप वास्तव में सिर, शरीर, सीएसएस और इतने पर बिना AJAX के "शुद्ध" HTML प्रस्तुत कर सकते हैं।

चाल है:

  • अपने नियंत्रक को एक प्रतिसाद देने के लिए \Magento\Framework\View\Result\Layoutकहें जो इसके बजाय टाइप का हो\Magento\Framework\View\Result\Page
  • रूट नोड के साथ लेआउट XML फ़ाइल का उपयोग करें जो इसके <layout...>...</layout>बजाय है<page...>...</page>

यहाँ एक बहुत ही सरल कार्यान्वयन है।

नियंत्रक

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

अभिन्यास

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

जीथुब पर उदाहरण

इस उदाहरण मॉड्यूल को देखें: https://github.com/herveguetin/Herve_AjaxLayout_M2

यह मॉड्यूल इसे उत्पन्न करता है:

यहाँ छवि विवरण दर्ज करें


क्या होगा अगर मैं पूरे लेआउट को लोड करना चाहता हूं (कुछ कंटेनरों, ब्लॉक आदि के साथ एक्सएमएल)? बनाएँ -> tottml, और json के माध्यम से ajax को भेजें?
मैटक्रूपनिक

5

बॉक्स से बाहर, Magento उन विधियों में से किसी को भी AJAX के माध्यम से HTML रेंडर करने के लिए उपयोग नहीं करता है।

मैंने जो देखा है, उसमें से हर चीज को करने की जरूरत है, JSON का उपयोग परिणाम के परिवहन के लिए किया जाता है।

से उदाहरण Magento/Checkout/Controller/Cart/Add:

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

तब Magento 2 एक नए तंत्र का उपयोग करता है जिसे अनुभाग कहा जाता है, डेटा को फ्रंटएंड पर हैंडल करने के लिए और उन विशिष्ट ब्लॉकों को अपडेट करने के लिए जिन्हें अपडेट करने की आवश्यकता है, आप इस Q & A में अनुभागों के बारे में अधिक जान सकते हैं: https://magento.stackexchange.com/a/ 143381/2380

मेरे उत्तर के दूसरे भाग के बारे में EDIT: टिप्पणी में मैक्स द्वारा कहा गया है, अनुभाग केवल ग्राहक विशिष्ट डेटा के साथ उपयोग किए जाते हैं और प्रत्येक AJAX कॉल के बजाय इस कार्यक्षमता का उपयोग करना सही समाधान नहीं है।


हां, मैं JSON का उपयोग परिणाम के परिवहन के लिए करता हूं, लेकिन मैं प्रश्न के उद्देश्य के लिए अपनी कक्षाओं को सरल बनाता हूं;) लेकिन मुझे उस अनुभाग सुविधा के बारे में पता नहीं है, यह वह करने का सही तरीका प्रतीत होता है जो मैं चाहता हूं। मैं इस पर एक नज़र डालूँगा। यदि कोई और प्रतिक्रिया है तो मैं प्रतीक्षा करूँगा अन्यथा मैं आपके उत्तर को मान्य करूँगा। धन्यवाद !
मत्तियो ज्योफ्रे

2
मैं कच्चे HTML डेटा के बजाय Json प्रतिक्रिया का उपयोग करने से सहमत हूं। लेकिन आपके उत्तर का दूसरा भाग पूर्ण सही नहीं है। ध्यान दें, कि ग्राहक अनुभाग केवल ग्राहक-विशिष्ट डेटा के लिए और प्रत्येक Ajax कॉल के बजाय इस कार्यक्षमता का उपयोग करना अच्छा विचार नहीं है।
मैक्स

2
@ Matthéo हाँ, मैं समझ गया :) जवाब सही करने के लिए राफेल को संबोधित मेरी टिप्पणी, क्योंकि उत्तर का दूसरा भाग अन्य उपयोगकर्ताओं द्वारा गलत समझा जा सकता है।
मैक्स

1
@MaxStsepantsevich को यह बताने के लिए धन्यवाद कि, मैंने अपने उत्तर को यह दिखाने के लिए संपादित किया है कि आपने क्या कहा है
राफेल डिजिटल पियानोवाद

1
मैंने आपकी प्रतिक्रिया का उपयोग करते हुए एक उत्तर जोड़ा। आपकी मदद के लिए धन्यवाद दो।
मत्तियो ज्योफ्रे

3

मेरे उदाहरण में मैं उपयोग नहीं कर सकता sectionsक्योंकि यह नहीं है customer dataऔर यह एक PUT/ POSTकार्रवाई के बाद नहीं है, लेकिन Raphael at Digital Pianismउत्तर का उपयोग करके मुझे पता चला कि मैगेंटो अनुभाग कैसे प्रस्तुत करता है।

यदि हम cartअनुभाग का उदाहरण लेते हैं तो यह \Magento\Customer\CustomerData\SectionPool::getSectionDataByNamesखंडों से डेटा प्राप्त करने के लिए विधि का उपयोग करता है । यह हमें \Magento\Checkout\CustomerData\Cart::getSectionDataखंड के क्षेत्रों सहित एकल सरणी के साथ ले जाता है$this->layout->createBlock('Magento\Catalog\Block\ShortcutButtons')->toHtml()

इसके आधार पर यहां अंतिम नियंत्रक वर्ग है:

<?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);
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.