<aside> ⚠️ // This page is incomplete.
</aside>
Entry points are pieces of information in the original Magento module that basically translate to a feature in ScandiPWA. Some things to be aware of are:
The layout files defined in the <MODULE>/view/frontend/layout
directory provide a good starting point for understanding what visual elements exist in the Magento module, and where they are used (with referenceContainer
, for example). Some examples of what can be found in this directory include:
view/frontend/layout/default
=> rendered on every page.view/frontend/layout/checkout_onepage_success
=> rendered on every checkout success page.view/frontend/layout/checkout_onepage_failure
=> rendered on every checkout failure page.<aside>
ℹ️ If there is a default.xml
, something is rendered on every page, look into this first.
</aside>
For example the layout view/frontend/layout/checkout_onepage_success
of the checkout module:
<page xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<title>Success Page</title>
</head>
<body>
<referenceBlock name="page.main.title">
<block class="Magento\\Checkout\\Block\\Onepage\\Success" name="checkout.success.print.button" template="Magento_Checkout::button.phtml"/>
<action method="setPageTitle">
<argument translate="true" name="title" xsi:type="string">Thank you for your purchase!</argument>
</action>
</referenceBlock>
<referenceContainer name="content">
<block class="Magento\\Checkout\\Block\\Onepage\\Success" name="checkout.success" template="Magento_Checkout::success.phtml" cacheable="false">
<container name="order.success.additional.info" label="Order Success Additional Info"/>
</block>
<block class="Magento\\Checkout\\Block\\Registration" name="checkout.registration" template="Magento_Checkout::registration.phtml" cacheable="false"/>
</referenceContainer>
</body>
</page>
Looking at this, its templates and blocks, you’ll know that in the Checkout page after completing the order:
page.main.title
:
content
:
<aside>
ℹ️ The referenceBlock
and referenceContainer
are important to determine the location of the feature.
</aside>
Layout files will lead you to two other important things:
.container.js
file in ScandiPWA..component.js
file in ScandiPWA.<aside>
ℹ️ Please do not confuse the block
tag in a layout file with the PHP block class that it uses to process the logic. You can find more information in the Magento 2 official documentation.
</aside>
Another important aspect to consider when looking at a layout file is the controller that uses it, as it serves as another entry point. (What to look into Magento controllers?)
Magento PHP blocks provide all the necessary logic for template rendering. Similarly, you should translate the block into something that provides all the necessary for the ScandiPWA component to function properly.
You should consider what is the best option to achieve the functionality. For example:
The desired functionality process some logic. You must implement the logic in a component container.
The desired functionality provides data that ScandiPWA currently has no access to.
You should implement a GraphQL query. This might be using the original block or other resources.
One example is the Checkout component:
Magento\\Checkout\\Block\\Onepage\\Success
And looking at the template that uses it, it basically needs:
canViewOrder
- In ScandiPWA if the user is logged.order.success.additional.info
. Which could become a render method in the component or another component.Template files are HTML code templates, that use some Block as logic and are rendered by it. The Block can be initialized from the Controller or from the layout file.
Taking as example the Magento_Checkout::success.phtml
template:
<?php /** @var $block \\Magento\\Checkout\\Block\\Onepage\\Success */ ?>
<div class="checkout-success">
<?php if ($block->getOrderId()) :?>
<?php if ($block->getCanViewOrder()) :?>
<p><?= $block->escapeHtml(__('Your order number is: %1.', sprintf('<a href="%s" class="order-number"><strong>%s</strong></a>', $block->escapeUrl($block->getViewOrderUrl()), $block->getOrderId())), ['a', 'strong']) ?></p>
<?php else :?>
<p><?= $block->escapeHtml(__('Your order # is: <span>%1</span>.', $block->getOrderId()), ['span']) ?></p>
<?php endif;?>
<p><?= $block->escapeHtml(__('We\\'ll email you an order confirmation with details and tracking info.')) ?></p>
<?php endif;?>
<?= $block->getAdditionalInfoHtml() ?>
<div class="actions-toolbar">
<div class="primary">
<a class="action primary continue" href="<?= $block->escapeUrl($block->getContinueUrl()) ?>"><span><?= $block->escapeHtml(__('Continue Shopping')) ?></span></a>
</div>
</div>
</div>
The Magento template should be translated to a ScandiPWA component. In this case, it was translated to the CheckoutSuccess component:
scandipwa/src/component/CheckoutSuccess/CheckoutSuccess.component.tsx
In the ScandiPWA example, the container passed some data as a prop to the component, which was previously accessed using the block in the original code.
<aside>
ℹ️ The CheckoutSuccess
component is rendered within the Checkout
component after the order is completed, as specified in the checkout_onepage_success
layout file.
</aside>
Consider what is the objective of the Magento controller:
Does it render a page?
Implement a ScandiPWA route or make it accessible through one, and implement the logic needed.
Does it return data, such as returning JSON for a GET request?
Implement a GraphQL query.
Does it modify data, such as handling a POST request?
Implement a GraphQL mutation.
One example of a controller that renders a page is the Checkout module implementation:
Basically, it makes some verifications before returning the result page.
magento/module-checkout/Controller/Index/Index.php
This functionality can be applied to the componentDidMount
. In ScandiPWA this is done in the Checkout
container:
componentDidMount(): void {
const {
guest_checkout,
updateMeta,
isGuestNotAllowDownloadable,
} = this.props;
const { email } = this.state;
this.handleRedirectIfNoItemsInCart();
this.handleRedirectIfLessThanMinAmountInCart();
// if guest checkout is disabled and user is not logged in => throw him to homepage
if (!guest_checkout && !isSignedIn()) {
history.push(appendWithStoreCode('/'));
}
// if guest is not allowed to checkout with downloadable => redirect to login page
if (!isSignedIn() && isGuestNotAllowDownloadable) {
this.handleRedirectIfDownloadableInCart();
}
if (email) {
this.checkEmailAvailability(email);
}
updateMeta({ title: __('Checkout') });
}
<aside> ℹ️ Note that you should define a route with the same path as the original for the component to be rendered.
</aside>
Tutorial: Create a YotPo compatibility extension
Tutorial: Create a Stripe compatibility extension
Tutorial: How to get extension’s config in FE?
Tutorial: Get any data from BE controllers in ScandiPWA FE using LocalStorage and inline <script/>