Đề bài
Các bạn hãy thêm một field input dạng date picker vào trong trang product detail với tên là Ngày nhận hàng. Khi người dùng click vào sẽ hiển thị bảng ngày, tháng để người dùng chọn.

Khi add to cart thì thêm ngày tháng vừa nhập vào giỏ hàng và hiển thị trong trang giỏ hàng như hình bên dưới:

Bài giải
Để giải được bài này đầu tiên các bạn phải tìm được layout của trang product detail và chèn thêm block của mình vào. Tất nhiên trước đó bạn phải tạo module trước đã:
Bước 1: Tạo module ViMagento_BT1
ViMagento/BT1/etc/module.xml
1 2 3 4 5 6 7 8 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="ViMagento_BT1" setup_version="1.0.0"> <sequence> <module name="Magento_Catalog"/> </sequence> </module> </config> |
ViMagento/BT1/registration.php
1 2 3 4 5 6 |
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'ViMagento_BT1', __DIR__ ); |
Sau đó chạy câu lệnh php bin/magento setup:upgrade để cài đặt module và xem module đã được cài thành công chưa rồi hãy làm bước tiếp theo nhé.
Bước 2: Override template
Như đề bài thì chúng ta phải thêm một block của chúng ta vào trang product detail. Và trang product detail có layout tên là catalog_product_view.xml, nên tôi sẽ override layout này để thêm block của tôi vào.
ViMagento/BT1/view/frontend/layout/catalog_product_view.xml
1 2 3 4 5 6 |
<?xml version="1.0"?> <page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="product.info" template="ViMagento_BT1::product/view/form.phtml" /> </body> </page> |
ViMagento/BT1/view/frontend/templates/product/view/form.phtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ // phpcs:disable Magento2.Templates.ThisInTemplate.FoundThis /** * Product view template * * @var $block \Magento\Catalog\Block\Product\View */ ?> <?php $_helper = $this->helper(Magento\Catalog\Helper\Output::class); ?> <?php $_product = $block->getProduct(); ?> <div class="product-add-form"> <form data-product-sku="<?= $block->escapeHtmlAttr($_product->getSku()) ?>" action="<?= $block->escapeUrl($block->getSubmitUrl($_product)) ?>" method="post" id="product_addtocart_form"<?php if ($_product->getOptions()) :?> enctype="multipart/form-data"<?php endif; ?>> <input type="hidden" name="product" value="<?= (int)$_product->getId() ?>" /> <input type="hidden" name="selected_configurable_option" value="" /> <input type="hidden" name="related_product" id="related-products-field" value="" /> <input type="hidden" name="item" value="<?= (int)$block->getRequest()->getParam('id') ?>" /> <div class="field"> <label style="font-weight: bold; display: block">Ngày nhận hàng: </label> <br> <input type="text" class="input-text" id="example-date" style="width: auto" name="example-date" /> </div> <?= $block->getBlockHtml('formkey') ?> <?= $block->getChildHtml('form_top') ?> <?php if (!$block->hasOptions()) :?> <?= $block->getChildHtml('product_info_form_content') ?> <?php else :?> <?php if ($_product->isSaleable() && $block->getOptionsContainer() == 'container1') :?> <?= $block->getChildChildHtml('options_container') ?> <?php endif;?> <?php endif; ?> <?php if ($_product->isSaleable() && $block->hasOptions() && $block->getOptionsContainer() == 'container2') :?> <?= $block->getChildChildHtml('options_container') ?> <?php endif;?> <?= $block->getChildHtml('form_bottom') ?> </form> </div> <script type="text/x-magento-init"> { "[data-role=priceBox][data-price-box=product-id-<?= $block->escapeHtml($_product->getId()) ?>]": { "priceBox": { "priceConfig": <?= /* @noEscape */ $block->getJsonConfig() ?> } } } </script> <script> require([ 'jquery', 'mage/translate', 'mage/calendar' ], function ($, $t) { $('#example-date').calendar({ changeMonth: true, changeYear: true, showButtonPanel: true, currentText: $t('Go Today'), closeText: $t('Close'), showWeek: true }); }) </script> <div class="field"> <label>Date and time of delivery : </label> <input type="text" class="input-text" id="example-date" style="width: auto" name="example-date" /> </div> <script> require([ 'jquery', 'mage/translate', 'mage/calendar' ], function ($, $t) { $('#example-date').calendar({ changeMonth: true, changeYear: true, showButtonPanel: true, currentText: $t('Go Today'), closeText: $t('Close'), showWeek: true }); }) </script> |
Ở file trên mình copy toàn bộ code của file form.php của catalog và thêm vào input của mình.
Sau khi xóa cache chúng ta sẽ chèn được ô input date picker như hình bên dưới:

Bước 2: Thêm Option vào giỏ hàng
Để làm được điều này thì bạn phải tìm được events sẽ xử lý khi chúng ta add to cart. Ở đây tôi sử dụng events checkout_cart_product_add_before.
ViMagento/BT1/etc/frontend/events.xml
1 2 3 4 5 6 |
<?xml version="1.0" encoding="utf-8" ?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> <event name="checkout_cart_product_add_before"> <observer name="addProductItemsToCart" instance="ViMagento\BT1\Observer\AdditionalOption" /> </event> </config> |
Sau đó tạo Observer để thêm option “Ngày giao hàng” vào giỏ hàng.
ViMagento/BT1/Observer/AdditionalOption.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?php namespace ViMagento\BT1\Observer; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; use Magento\Framework\Serialize\Serializer\Json; use Magento\Framework\App\RequestInterface; class AdditionalOption implements ObserverInterface { protected $_request; protected $serializer; public function __construct(RequestInterface $request, Json $serializer) { $this->_request = $request; $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Framework\Serialize\Serializer\Json::class); } public function execute(Observer $observer) { $date = $this->_request->getParam('example-date'); $product = $observer->getProduct(); $additionalOptions = []; $additionalOptions[] = array( 'label' => "Ngày giao hàng: ", 'value' => $date, ); $product->addCustomOption('additional_options', $this->serializer->serialize($additionalOptions)); } } |
Sau cùng các bạn xóa cache và thêm một sản phẩm vào giỏ hàng của mình, và đây là kết quả mà tôi thu được:

Và ở trang chi tiết giỏ hàng:

Kết luận
Vừa rồi là một bài tập đơn giản về cách để thêm một custom html vào trang. Nếu các bạn có thắc mắc gì về bài giải hoặc có cách làm hay hơn, nhanh hơn hãy để lại bình luận bên dưới nhé.
ra theem bai tap di anhh