поэтому я пытаюсь создать особый тип блока «карточка продукта» на главной странице M2. Идея состоит в том, что блок с информацией о продукте для выбранного в данный момент продукта в раскрывающемся списке
Я реализовал следующие файлы, чтобы попытаться достичь этой цели:
приложение/код/поставщик/модуль/представление/интерфейс/веб/js/представление/подписки-group.js
/**
* @category Vendor
* @package Vendor\Module
* @copyright Copyright (c) 2021 Vendor Media Limited (http://www.Vendor.co.uk/)
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
*/
define([
'uiElement',
'underscore',
'jquery',
'ko',
'mage/translate',
'Magento_Ui/js/model/messageList'
], function (Element, _, $, ko, $t, messageList) {
'use strict';
return Element.extend({
defaults: {
template: 'Vendor_Module/products-group',
productGroup: null,
ajaxHttpMethod: 'POST',
productsRendered: 0,
productData: ko.observableArray([]),
currentId: ko.observable(0),
currentProduct: ko.pureComputed(function () { return {};}).bind(this),
imports: {
ajaxUrl: '${ $.provider }:ajaxUrl',
showDescription: '${ $.provider }:showDescription'
}
},
loadingInProgress: ko.observable(false),
errorMessage: ko.observable(null),
warningMessage: ko.observable(null),
initialize: function () {
this._super();
ko.options.deferUpdates = true;
let self = this;
this.currentProduct = ko.pureComputed(function (){
return self.productData[self.currentId()] || {};
}, self).bind(this);
this.getProductData()
.done(function(response) {
Object.values(JSON.parse(response)).forEach(function(product) {
self.productData.push(product);
});
self.currentId.valueHasMutated();
console.log(self.currentProduct());
}, self)
.fail(function(err) {
console.error(`Failed to get product data for group ${ self.productGroup }`);
console.error(err.message);
}, self);
return this;
},
getProductData: function() {
return $.ajax({
accepts: {
text: "application/json"
},
url: this.ajaxUrl,
type: this.ajaxHttpMethod,
dataType: 'json',
data: {
group: this.productGroup
}
})
}
});
});
app/code/Vendor/Module/view/frontend/templates/subscription-list.phtml
/** @var Subscriptions $block */
$_productCollection = $block->getProducts();
/** @var Vendor\Module\Helper\Config $_configHelper */
$_configHelper = $this->helper(ConfigHelper::class);
// Display definitions
$viewMode = 'list';
$image = 'category_page_list_image';
$showDescription = true;
$i = 0;
?>
<?php if (!$_productCollection || !count($_productCollection)): ?>
<div class="message info empty">
<div><?php
echo __('You do not have any subscriptions.') ?></div>
</div>
<?php else: ?>
<div class="products wrapper <?= $viewMode ?> products-<?= $viewMode ?>" data-bind="scope: 'subscriptionsList'">
<ol class="products list items product-items">
<!-- ko foreach: elems() -->
<li class="item product product-item product-item-info" data-container="product-grid" data-bind="template: { name: getTemplate(), data: currentProduct}">
</li>
<!-- /ko -->
</ol>
</div>
<?php endif; ?>
<script>
window.subscriptionConfig = <?= Zend_Json::encode($block->getSubscriptionConfig()) ?>;
</script>
<script type="text/x-magento-init">
{
"*": {
"Magento_Ui/js/core/app": {
"components": {
"subscriptionsList": {
"component": "Vendor_Module/js/view/subscriptions-list",
"config": {
"ajaxUrl": "<?= $block->getUrl($_configHelper::PRODUCT_DATA_AJAX_URL) ?>",
"showDescription": "<?= json_encode($block->showDescription()) ?>",
"viewMode": "<?= $viewMode ?>",
"image": "<?= $image ?>"
},
"children": {
"groupListIncontrol": {
"component": "Vendor_Module/js/view/subscriptions-group",
"config": {
"provider": "subscriptionsList",
"productGroup": "<?= $_configHelper::PRODUCT_GROUP_INCONTROL ?>"
}
},
"groupListOnlinePack": {
"component": "Vendor_Module/js/view/subscriptions-group",
"config": {
"provider": "subscriptionsList",
"productGroup": "<?= $_configHelper::PRODUCT_GROUP_ONLINE_PACK ?>"
}
}
}
}
}
}
}
}
</script>
app/code/Vendor/Module/view/frontend/web/template/products-group.html (это находится в процессе преобразования чистого php в ko, так что выглядит беспорядок, приносим извинения)
<!--
@category Vendor
@package Vendor\Module
@copyright Copyright (c) 2021 Vendor Media Limited (http://www.Vendor.co.uk/)
@license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
-->
<!--Fix product group to be dynamic-->
<!--<ol class="products list items product-items" data-bind="class: productGroup">-->
<!-- <div class="top-product-container">-->
<!-- <span class="name-wrapper" data-bind="accessObj: { obj: currentProduct, key: 'name' } "></span>-->
<!--<!– <?php echo $block->getProductPrice($_product) ?>–>-->
<!-- <div class="price-box price-final_price" data-role="priceBox" data-product-id="5406" data-price-box="product-id-5406">-->
<!-- <span class="price-container price-final_price tax weee">-->
<!-- <span id="product-price-5406" data-price-amount="99" data-price-type="finalPrice" class="price-wrapper "><span class="price" data-bind="accessObj: { obj: currentProduct, key: 'price' }"></span></span>-->
<!-- </span>-->
<!-- </div>-->
<!-- </div>-->
<!--</ol>-->
<span class="stripped-name" data-bind="text: nameStripped" style="display: none;"></span>
<div class="top-product-container">
<!-- <?php echo $block->getProductPrice($_product) ?>-->
<label for="select_subscription_<?php echo $i ?>" class="product name product-item-name">
<span class="name-wrapper" data-bind="text: name"></span>
</label>
<div class="price-box price-final_price" data-role="priceBox" data-product-id="5406" data-price-box="product-id-5406">
<span class="price-container price-final_price tax weee">
<span id="product-price-5406" data-price-amount="99" data-price-type="finalPrice" class="price-wrapper "><span class="price" data-bind="text: getCurrentAttribute('price')"></span></span>
</span>
</div>
</div>
<div class="info-container">
<div class="product-image" data-bind="text: getCurrentAttribute('imageHtml')">
</div>
<div class="info-block">
<?php if ($showDescription):?>
<div class="product description product-item-description">
<?php echo $_helper->productAttribute($_product, $_product->getShortDescription(), 'short_description'); ?>
<?php $longDesc = $_helper->productAttribute($_product, $_product->getDescription(), 'description'); ?>
<?php if ($longDesc): ?>
<?php if (!$block->showDescription()): ?>
<a onclick="jQuery(this).next().toggle(); jQuery(this).hide();" title="<?php echo $_productNameStripped ?>" class="action more">
<?php echo __('Read More...'); ?>
</a>
<?php endif; ?>
<div class="long-desc" <?php if ($block->showDescription()): ?>style="display: block;"<?php endif; ?>>
<?php echo $longDesc; ?>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if ($note = $_helper->productAttribute($_product, $_product->getProductNote(), 'product_note')): ?>
<div class="note">
<?php echo $note ?>
</div>
<?php endif; ?>
</div>
</div>
В UiComponent я вызываю контроллер M2 JSON, который возвращает список объектов JSON, каждый из которых представляет собой все соответствующие данные о продукте для отображения для product_id. Я проверил с помощью отладчика, что эти данные поступают
Итак, есть 2 проблемы с ним:
subscriptions-list.phtml
не нравитсяdata-bind="template: { name: getTemplate(), data: currentProduct}"
, он говорит: «невозможно прочитать имя свойства» неопределенного. Я попытался создать эту привязку шаблона по совету этот ответ- Когда страница загружается, оба
this.productData
наблюдаемых массива показывают точно одни и те же данные, хотя я собственными глазами убедился, что они получают разные ответы данных (отладчик). Мне кажется, что это свойство каким-то образом распределяется между дочерними элементами, потому что оно заканчивается конкатенацией обоих массивов, возвращаемых из контроллера