Intento encontrar la mejor manera de representar HTML a través de AJAX en Magento 2.
Forma 1: uso del controlador sin diseño
Archivo 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());
}
}
Forma 2: uso del controlador con diseño personalizado
Archivo 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();
}
}
Archivo 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>
Archivo 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>
En mi opinión, la mejor práctica parece ser el camino 2 porque separa la lógica del controlador.
Pero el problema con Way 2 es que se generan <body>
y <head>
con CSS
/ JS
, por lo que no es un HTML completamente limpio con solo mi plantilla de bloque.
- ¿Estoy usando el diseño personalizado de forma incorrecta?
- ¿El Camino 1 se considera una buena práctica?
- ¿Hay alguna otra forma de hacer eso?
fuente
Fuera de la caja, Magento no utiliza ninguno de esos métodos para representar HTML a través de AJAX.
Por lo que he visto, cada vez que hay que hacer algo así, JSON se utiliza para transportar el resultado.
Ejemplo de
Magento/Checkout/Controller/Cart/Add
:Luego, Magento 2 usa un nuevo mecanismo llamado secciones, para manejar los datos en la interfaz y actualizar los bloques específicos que deben actualizarse, puede obtener más información sobre las secciones en estas preguntas y respuestas: /magento//a/ 143381/2380
EDITAR con respecto a la segunda parte de mi respuesta: como dijo Max en el comentario, las secciones solo se usan con datos específicos del cliente y usar esta funcionalidad en lugar de cada llamada AJAX no es la solución correcta.
fuente
En mi ejemplo, no puedo usar
sections
porque no lo escustomer data
y no es después de unaPUT
/POST
acción, pero usando laRaphael at Digital Pianism
respuesta descubrí cómo Magento renderiza las secciones.Si tomamos el ejemplo de la
cart
sección, use el método\Magento\Customer\CustomerData\SectionPool::getSectionDataByNames
para recuperar datos de las secciones. Esto nos lleva a\Magento\Checkout\CustomerData\Cart::getSectionData
una única matriz que contiene áreas de la sección, incluyendo$this->layout->createBlock('Magento\Catalog\Block\ShortcutButtons')->toHtml()
Dependiendo de eso, aquí está la clase de controlador final:
fuente