【发布时间】:2020-02-06 13:22:01
【问题描述】:
我在 magento 2.3 中创建小部件,以扩展供应商目录列表产品的功能。默认情况下,目录列表产品 (CLP) 不允许在同一页面上创建和处理多个条件控件。我的小部件允许创建多个条件控件。 从技术上讲,我的每个条件控件都在新的模式窗口中打开。 当用户需要创建条件时,他必须点击名为“选择”的按钮 模态窗口打开,用户设置条件。当用户配置并准备好保存条件时,他单击模式窗口 ajax 请求发送到服务器上名为“保存”的按钮,服务器将解码后的值响应父表单输入。用户关闭模态窗口并单击父表单上的保存按钮。小部件已保存。全做完了。在这一步之前一切都是正确的: 当用户想要编辑保存的小部件并打开模态窗口时,保存的数据由另一个 ajax 和 jQuery Prepend newchild 转换为适用的形式 到
但前置数据变得不可交互 - 用户无法编辑和删除加载的规则。 小部件.xml
<parameter name="cond1" xsi:type="block" visible="true" required="false">
<label translate="true">First Conditions</label>
<block class="MonteShot\MegaWidget\Block\Adminhtml\Conditions\Conditions">
<data>
<item name="condition" xsi:type="array">
<item name="id1" xsi:type="string" translate="true">1</item>
</item>
</data>
</block>
</parameter>
MonteShot\MegaWidget\Block\Adminhtml\Conditions\Conditions
<?php
namespace MonteShot\MegaWidget\Block\Adminhtml\Conditions;
use Magento\Backend\Block\Widget\Form\Generic;
use Magento\Backend\Block\Widget\Tab\TabInterface;
use Magento\Widget\Block\BlockInterface;
/**
* Class Conditions
*/
class Conditions extends Generic implements TabInterface, BlockInterface
{
/**
* Conditions constructor.
* @param \Magento\Backend\Block\Template\Context $context
* @param \Magento\Framework\Data\FormFactory $formFactory
* @param \Magento\Rule\Block\Conditions $conditions
* @param \Magento\Backend\Block\Widget\Form\Renderer\Fieldset $rendererFieldset
* @param \Magento\Framework\Registry $coreRegistry
* @param \MonteShot\MegaWidget\Model\RuleFactory $ruleModelFactory
* @param \Magento\CatalogWidget\Model\RuleFactory $ruleFactory
* @param \Magento\Widget\Helper\Conditions $conditionsHelper
* @param \Magento\Cms\Model\PageFactory $pageFactory
* @param \Magento\Framework\App\Response\Http $response
* @param array $data
*/
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\Framework\Data\FormFactory $formFactory,
\Magento\Rule\Block\Conditions $conditions,
\Magento\Backend\Block\Widget\Form\Renderer\Fieldset $rendererFieldset,
\Magento\Framework\Registry $coreRegistry,
\MonteShot\MegaWidget\Model\RuleFactory $ruleModelFactory,
\Magento\CatalogWidget\Model\RuleFactory $ruleFactory,
\Magento\Widget\Helper\Conditions $conditionsHelper,
\Magento\Cms\Model\PageFactory $pageFactory,
\Magento\Framework\App\Response\Http $response,
array $data = []
)
{
$this->response = $response;
$this->conditionsHelper = $conditionsHelper;
$this->ruleFactory = $ruleFactory;
$this->ruleModelFactory = $ruleModelFactory;
$this->_pageFactory = $pageFactory;
$this->coreRegistry = $coreRegistry;
$this->rendererFieldset = $rendererFieldset;
$this->conditions = $conditions;
parent::__construct($context, $coreRegistry, $formFactory, $data);
}
/**
* {@inheritdoc}
*/
public function getTabLabel()
{
return __('Conditions');
}
/**
/**
* @param \Magento\Framework\Data\Form\Element\AbstractElement $element
* @return \Magento\Framework\Data\Form\Element\AbstractElement
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function prepareElementHtml(\Magento\Framework\Data\Form\Element\AbstractElement $element)
{
$uniqId = $this->mathRandom->getUniqueHash($element->getId());
$sourceUrl = $this->getUrl(
'megawidget/conditions_rule_conditioncontent/conditionpagecontroller',
[
'name' => $element->getData('name'),
'uniq_id' => $uniqId,
'button_num' => $this->getData('condition')[key($this->getData('condition'))]
]);
$chooser = $this->getLayout()->createBlock(
\MonteShot\MegaWidget\Block\Adminhtml\Widget\Chooser::class
)->setElement(
$element
)->setConfig(
$this->getConfig()
)->setFieldsetId(
$this->getFieldsetId()
)->setSourceUrl(
$sourceUrl
)->setUniqId(
$uniqId
)->setValue($this->getData('condition')[key($this->getData('condition'))]);
if ($element->getValue()) {
$page = $this->_pageFactory->create()->load((int)$element->getValue());
if ($page->getId()) {
$chooser->setLabel($this->escapeHtml($page->getTitle()));
}
}
$element->setData('after_element_html', $chooser->toHtml());
return $element;
}
/**
* Prepare form before rendering HTML
*
* @return Generic
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function _prepareForm()
{
$model = $this->ruleFactory->create();
// $model = $this->ruleModelFactory->create();
$id = $this->_request->getParam('uniq_id');
$name = $this->_request->getParam('name');
$cuttedName = trim(str_replace('parameters', '', $name), '[]');
/** @var \Magento\Framework\Data\Form $form */
$form = $this->_formFactory->create(
[
'data' => [
'id' => 'edit_form_modal',
'action' => $this->getUrl('megawidget/conditions_rule/savewidget',
[
'uniq_id' => $this->_request->getParam('uniq_id'),
'button_num' => $this->_request->getParam('button_num'),
'name' => $this->_request->getParam('name'),
]),
'method' => 'post',
],
]
);
$form->setUseContainer(true);
$form->setHtmlIdPrefix('rule_');
$this->getLayout()->createBlock("Magento\Widget\Block\Adminhtml\Widget\Options");
$renderer = $this->rendererFieldset->setTemplate(
'Magento_CatalogRule::promo/fieldset.phtml'
)->setNewChildUrl(
$this->getUrl('megawidget/conditions_rule/newConditionHtmlCatalog/form/rule_conditions_fieldset')
);
$fieldset = $form->addFieldset(
'conditions_fieldset',
[
'legend' => __(
'Apply the rule only if the following conditions are met (leave blank for all products).'
)
]
)->setRenderer(
$renderer
);
// $model->getConditions()->setJsFormObject('rule_conditions_fieldset');
// $model->setData('element_value', substr_replace($_POST['element_value'], '', 0, 26));
$model->getConditions()->setJsFormObject('rule_conditions_fieldset');
$fieldset->addField(
'conditions',
'text',
['name' => 'conditions', 'label' => __('Conditions'), 'title' => __('Conditions')]
)->setRule(
$model
)->setRenderer(
$this->conditions
);
$label = $id . 'label';
$valueId = $id . 'value';
$fieldset->addField(
'button-save',
'hidden',
['name' => 'select',
'label' => __('Save condition'),
'title' => __('Save condition'),
'class' => 'action-close',
'data-role' => 'closeBtn',
'data_attribute' => [
'mage-init' => ['button' => ['event' => 'saveandcontinue', 'target' => '#edit_form']],
],
'after_element_html' => '
<button data-role="closeBtn" id="rule_button-save-submit-' . $cuttedName . '" type="button">Save</button>
<script>
require([\'jquery\',\'jqueryForm\',\'Magento_Ui/js/modal/modal\'], function (jQuery,jqueryForm,modal){
jQuery(document).on(\'click\', "#rule_button-save-submit-' . $cuttedName . '", function () {
var serArr=JSON.stringify(jQuery("#edit_form_modal").serializeArray());
jQuery.ajax({
url: "' . $this->getUrl("megawidget/conditions_rule/preparedata") . '",
data: { form_key: window.FORM_KEY,serializedArray:serArr},
type: \'post\',
success: function (response) {
console.log(response.data);
jQuery("input[name=\'' . $name . '\']")[0].value=response.data;
},
error: function (response) {
alert(response.message);
console.log(response.message);
}
});
});
});
</script>
']);
$fieldset->addField(
'script-area',
'hidden',
['name' => 'select',
'class' => 'script-area-hidden',
'data_attribute' => [
'mage-init' => ['hidden' => ['event' => 'saveandcontinue', 'target' => '#edit_form_modal']],
],
'after_element_html' => '
<script>
require([\'jquery\',\'jqueryForm\'],
function ($,jqueryForm){
jQuery(document).ready(function (jQuery) {
jQuery.ajax({
url: "' . $this->getUrl("megawidget/conditions_rule/newConditionHtmlCatalog/form/rule_conditions_fieldset") . '",
data: {JsonToHtml:jQuery("input[name=\'' . $name . '\']")[0].value, form: window.FORM_KEY},
type: \'post\',
success: function (response) {
console.log(response.data);
jQuery(document.querySelector("#conditions__1__children")).prepend(response.data);
},
error: function (response) {
alert(response.message);
console.log(response.message);
}
});
});
});
</script>
']);
// $model->getConditions()->setJsFormObject('rule_conditions_fieldset');
$form->setValues($model->getData());
$this->setForm($form);
return parent::_prepareForm();
}
}
//Magento\Widget\Helper\Conditions encode when save button has been pressed
模态窗口中的代码
$model = $this->ruleFactory->create();
// $model = $this->ruleModelFactory->create();
$id = $this->_request->getParam('uniq_id');
$name = $this->_request->getParam('name');
$cuttedName = trim(str_replace('parameters', '', $name), '[]');
/** @var \Magento\Framework\Data\Form $form */
$form = $this->_formFactory->create(
[
'data' => [
'id' => 'edit_form_modal',
'action' => $this->getUrl('megawidget/conditions_rule/savewidget',
[
'uniq_id' => $this->_request->getParam('uniq_id'),
'button_num' => $this->_request->getParam('button_num'),
'name' => $this->_request->getParam('name'),
]),
'method' => 'post',
],
]
);
$form->setUseContainer(true);
$form->setHtmlIdPrefix('rule_');
$this->getLayout()->createBlock("Magento\Widget\Block\Adminhtml\Widget\Options");
$renderer = $this->rendererFieldset->setTemplate(
'Magento_CatalogRule::promo/fieldset.phtml'
)->setNewChildUrl(
$this->getUrl('megawidget/conditions_rule/newConditionHtmlCatalog/form/rule_conditions_fieldset')
);
$fieldset = $form->addFieldset(
'conditions_fieldset',
[
'legend' => __(
'Apply the rule only if the following conditions are met (leave blank for all products).'
)
]
)->setRenderer(
$renderer
);
// $model->getConditions()->setJsFormObject('rule_conditions_fieldset');
// $model->setData('element_value', substr_replace($_POST['element_value'], '', 0, 26));
$model->getConditions()->setJsFormObject('rule_conditions_fieldset');
$fieldset->addField(
'conditions',
'text',
['name' => 'conditions', 'label' => __('Conditions'), 'title' => __('Conditions')]
)->setRule(
$model
)->setRenderer(
$this->conditions
);
// $fieldset->addElement($this->getLayout()->createBlock(\MonteShot\MegaWidget\Renderer\Conditions::class));
$label = $id . 'label';
$valueId = $id . 'value';
$fieldset->addField(
'button-save',
'hidden',
['name' => 'select',
'label' => __('Save condition'),
'title' => __('Save condition'),
'class' => 'action-close',
'data-role' => 'closeBtn',
'data_attribute' => [
'mage-init' => ['button' => ['event' => 'saveandcontinue', 'target' => '#edit_form']],
],
'after_element_html' => '
<button data-role="closeBtn" id="rule_button-save-submit-' . $cuttedName . '" type="button">Save</button>
<script>
require([\'jquery\',\'jqueryForm\',\'Magento_Ui/js/modal/modal\'], function (jQuery,jqueryForm,modal){
jQuery(document).on(\'click\', "#rule_button-save-submit-' . $cuttedName . '", function () {
var serArr=JSON.stringify(jQuery("#edit_form_modal").serializeArray());
jQuery.ajax({
url: "' . $this->getUrl("megawidget/conditions_rule/preparedata") . '",
data: { form_key: window.FORM_KEY,serializedArray:serArr},
type: \'post\',
success: function (response) {
console.log(response.data);
jQuery("input[name=\'' . $name . '\']")[0].value=response.data;
},
error: function (response) {
alert(response.message);
console.log(response.message);
}
});
});
});
</script>
']);
$fieldset->addField(
'script-area',
'hidden',
['name' => 'select',
'class' => 'script-area-hidden',
'data_attribute' => [
'mage-init' => ['hidden' => ['event' => 'saveandcontinue', 'target' => '#edit_form_modal']],
],
'after_element_html' => '
<script>
require([\'jquery\',\'jqueryForm\'],
function ($,jqueryForm){
jQuery(document).ready(function (jQuery) {
jQuery.ajax({
url: "' . $this->getUrl("megawidget/conditions_rule/newConditionHtmlCatalog/form/rule_conditions_fieldset") . '",
data: {JsonToHtml:jQuery("input[name=\'' . $name . '\']")[0].value, form: window.FORM_KEY},
type: \'post\',
success: function (response) {
console.log(response.data);
jQuery(document.querySelector("#conditions__1__children")).prepend(response.data);
},
error: function (response) {
alert(response.message);
console.log(response.message);
}
});
});
});
</script>
']);
$form->setValues($model->getData());
$this->setForm($form);
return parent::_prepareForm();
}
准备数据控制器
<?php
/**
* Copyright (c) 2019. MonteShot
*/
namespace MonteShot\MegaWidget\Controller\Adminhtml\Conditions\Rule;
use Magento\Framework\Json\Helper\Data as JsonHelper;
/**
* Class PrepareData
*/
class PrepareData extends \MonteShot\MegaWidget\Controller\Adminhtml\Conditions\Rule
{
/**
* @param \Magento\Backend\App\Action\Context $context
* @param \Magento\Framework\Registry $coreRegistry
* @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory
* @param \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter
* @param \MonteShot\MegaWidget\Model\RuleFactory $ruleFactory
* @param \Magento\Widget\Helper\Conditions $conditionsHelper
* @param \Psr\Log\LoggerInterface $logger
* @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
* @param JsonHelper $jsonHelper
*/
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Registry $coreRegistry,
\Magento\Framework\App\Response\Http\FileFactory $fileFactory,
\Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter,
\MonteShot\MegaWidget\Model\RuleFactory $ruleFactory,
\Magento\Widget\Helper\Conditions $conditionsHelper,
\Psr\Log\LoggerInterface $logger,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
JsonHelper $jsonHelper
)
{
$this->jsonHelper = $jsonHelper;
$this->resultJsonFactory = $resultJsonFactory;
$this->conditionsHelper = $conditionsHelper;
parent::__construct($context, $coreRegistry, $fileFactory, $dateFilter, $ruleFactory, $logger);
}
/**
* @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Json|\Magento\Framework\Controller\ResultInterface|void
*/
public function execute()
{
if (!$this->getRequest()->getPostValue()) {
$this->_redirect('megawidget/*/');
}
try {
$serializedConditionArray =
$this->conditionsHelper->decode($this->getRequest()->getParam('serializedArray'));
$templateArray = [];
foreach ($serializedConditionArray as $index => $singleArrItem) {
if ($singleArrItem['name'] == 'form_key') {
unset($serializedConditionArray[$index]);
continue;
}
if ($singleArrItem['name'] == 'select') {
unset($serializedConditionArray[$index]);
continue;
}
if (!empty($templateArray[str_replace('rule', '', $singleArrItem['name'])])) {
$templateArray[str_replace('rule', '', $singleArrItem['name'])] .= ',' . $singleArrItem['value'];
} else {
$templateArray[str_replace('rule', '', $singleArrItem['name'])] = $singleArrItem['value'];
}
//$templateArray[str_replace('rule', '', $singleArrItem['name'])] = $singleArrItem['value'];
}
$finalArr = [];
foreach ($templateArray as $index => $data) {
$indexName = $this->get_string_between(str_replace('[conditions]', '', $index), '[', ']');
$paramName = $this->get_string_between(str_replace('[conditions][' . $indexName . ']', '', $index), '[', ']');
$multiValue = str_replace('parameters[conditions][' . $indexName . ']' . '[' . $paramName . ']', '', $index);
if ($paramName == 'value' && strpos($data, ',')) {
$finalArr[$indexName][$paramName] = [$data];
} else {
$finalArr[$indexName][$paramName] = $data;
}
if ($paramName == 'value' && $multiValue == '[]') {
if ($finalArr[$indexName][$paramName]) {
if ($finalArr[$indexName][$paramName]) {
$temp = $finalArr[$indexName][$paramName];
unset($finalArr[$indexName][$paramName]);
$finalArr[$indexName][$paramName][0] = $data;
} else {
$finalArr[$indexName][$paramName][0] .= ',' . $data;
}
} else {
$finalArr[$indexName][$paramName][0] = [$data];
}
}
}
$this->data = $this->conditionsHelper->encode($finalArr);
$this->message = 'success';
} catch (\Magento\Framework\Exception\LocalizedException $e) {
$this->messageManager->addErrorMessage($e->getMessage());
$id = (int)$this->getRequest()->getParam('rule_id');
if (!empty($id)) {
$this->_redirect('megawidget/*/edit', ['id' => $id]);
} else {
$this->_redirect('megawidget/*/new');
}
return;
} catch (\Exception $e) {
$this->messageManager->addErrorMessage(
__('Something went wrong while saving the rule data. Please review the error log.')
);
$this->error = $e->getMessage();
$this->message = 'success';
$this->logger->critical($e);
$data = !empty($data) ? $data : [];
$this->_session->setPageData($data);
$this->_redirect('megawidget/*/edit', ['id' => $this->getRequest()->getParam('rule_id')]);
return;
}
$resultJson = $this->resultJsonFactory->create();
$resultData = substr(substr($this->jsonHelper->jsonEncode($this->data), 1), 0, -1);
return $resultJson->setData([
'message' => $this->message,
'data' => $resultData,
'error' => $this->error
]);
}
protected function get_string_between($string, $start, $end)
{
$string = ' ' . $string;
$ini = strpos($string, $start);
if ($ini == 0) return '';
$ini += strlen($start);
$len = strpos($string, $end, $ini) - $ini;
return substr($string, $ini, $len);
}
}
返回数据的控制器准备在 jQuery 中添加
<?php
/**
* Copyright (c) 2019. MonteShot
*/
namespace MonteShot\MegaWidget\Controller\Adminhtml\Conditions\Rule;
use Magento\Framework\Json\Helper\Data as JsonHelper;
class NewConditionHtmlCatalog extends \MonteShot\MegaWidget\Controller\Adminhtml\Conditions\Rule
{
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Registry $coreRegistry,
\Magento\Framework\App\Response\Http\FileFactory $fileFactory,
\Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter,
\MonteShot\MegaWidget\Model\RuleFactory $ruleFactory,
\Psr\Log\LoggerInterface $logger,
\Magento\Widget\Helper\Conditions $conditions,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
JsonHelper $jsonHelper,
\Magento\CatalogWidget\Model\RuleFactory $ruleCatalogFactory,
\Magento\Rule\Model\Condition\CombineFactory $combineModelFactory
)
{
$this->combineModelFactory = $combineModelFactory;
$this->ruleCatalogFactory = $ruleCatalogFactory;
$this->jsonHelper = $jsonHelper;
$this->resultJsonFactory = $resultJsonFactory;
$this->conditions = $conditions;
parent::__construct($context, $coreRegistry, $fileFactory, $dateFilter, $ruleFactory, $logger);
}
public function execute()
{
if (!empty($this->getRequest()->getParam('id'))) {
$id = $this->getRequest()->getParam('id');
$typeArr = explode('|', str_replace('-', '/', $this->getRequest()->getParam('type')));
$type = $typeArr[0];
$model = $this->_objectManager->create(
$type
)->setId(
$id
)->setType(
$type
)->setRule(
$this->ruleFactory->create()
)->setPrefix(
'conditions'
);
if (!empty($typeArr[1])) {
$model->setAttribute($typeArr[1]);
}
if ($model instanceof \Magento\Rule\Model\Condition\AbstractCondition) {
$model->setJsFormObject($this->getRequest()->getParam('form'));
$html = $model->asHtmlRecursive();
} else {
$html = '';
}
return $this->getResponse()->setBody($html);
} elseif (!empty($this->getRequest()->getParam('JsonToHtml'))) {
$conditionDecoded = $this->conditions->decode($this->getRequest()->getParam('JsonToHtml'));
foreach ($conditionDecoded as $idx => $condition) {
if ($idx == '1') {
continue;
} else {
$id = $idx;
$type = $conditionDecoded[$idx]['type'];
$rule = $this->ruleCatalogFactory->create();
// $rule->setConditions($conditionDecoded);
$combineModel = $this->combineModelFactory->create();
$combineModel->loadArray($conditionDecoded);
$validateResult = $rule->validateData(new \Magento\Framework\DataObject($rule->getData()));
if ($validateResult !== true) {
foreach ($validateResult as $errorMessage) {
$this->message = $errorMessage;
}
return;
}
$rule->loadPost($rule->getData());
$model = $this->_objectManager->create(
$type
)->setId(
$id
)->setType(
$type
)->setPrefix(
'conditions'
)->setData(
'conditions', $rule
)->setRule(
$rule
);
if (!empty($conditionDecoded[$idx]['attribute'])) {
$model->setAttribute($conditionDecoded[$idx]['attribute']);
}
if (!empty($conditionDecoded[$idx]['value'])) {
$model->setValue($conditionDecoded[$idx]['value']);
}
}
if ($model instanceof \Magento\Rule\Model\Condition\AbstractCondition) {
// if (empty($this->data)) {
// $model->setJsFormObject($this->getRequest()->getParam('form'));
// $this->data = '<li class>' . $model->asHtmlRecursive() . '</li>';
// $this->data = $model->asHtmlRecursive();
// } else {
$model->setJsFormObject($this->getRequest()->getParam('form'));
$this->data = '<li class>' . $model->asHtmlRecursive() . '</li>';
//$this->data = $this->data . "\n" . '<li class>' . $model->asHtmlRecursive() . '</li>';
// }
} else {
$this->data = '';
}
$this->getResponse()->setBody($this->data);
}
}
}
// return $this->getResponse()->setBody($this->data);
$resultJson = $this->resultJsonFactory->create();
return $resultJson->setData([
'message' => $this->message,
'data' => $this->data,
'error' => $this->error
]);
}
}
如何将交互性返回到加载的数据
【问题讨论】:
标签: javascript php jquery html magento2