Проблема с SuperBoxSelect
Всем привет. Пытаюсь в modExtra добавить поле со множественным выбором из списка товаров msProduct. Удалось прикрутить саму форму select и вывести продукты, но существует проблема с сохранением и выводом в поле сохранённых товаров.
Делаю следующим образом. В схему добавляю:
В combo.js у меня такой код:
Помогите разобраться с сохранением и выводом при редактировании.
UPD: Теперь всё сохраняется, но не отображается выбор.
Делаю следующим образом. В схему добавляю:
<field key="products" dbtype="text" phptype="json" null="true"/>
В combo.js у меня такой код:
modExtra.combo.Options = function(config) {
config = config || {};
Ext.applyIf(config,{
xtype:'superboxselect',
allowBlank: true,
msgTarget: 'under',
allowAddNewData: true,
addNewDataOnBlur : true,
resizable: true,
name: 'products',
anchor:'99%',
minChars: 1,
fieldLabel: _('ms2_product_name'),
valueField: 'id',
displayField: 'pagetitle',
url: modExtra.config['connector_url'],
store:new Ext.data.JsonStore({
id: (config.name || 'products') + '-store',
root:'results',
autoLoad: true,
autoSave: false,
totalProperty:'total',
fields: ['id', 'pagetitle', 'parents'],
value: '{products}',
url: modExtra.config['connector_url'],
baseParams: {
action: 'mgr/product/getoptions',
key: config.name
},
tpl: new Ext.XTemplate('\
<tpl for=".">\
<div class="x-combo-list-item minishop2-product-list-item" ext:qtip="{pagetitle}">\
<tpl if="parents">\
<span class="parents">\
<tpl for="parents">\
<nobr><small>{pagetitle} / </small></nobr>\
</tpl>\
</span>
\
</tpl>\
<span><small>({id})</small> <b>{pagetitle}</b></span>\
</div>\
</tpl>', {compiled: true}
),
}),
mode: 'remote',
triggerAction: 'all',
extraItemCls: 'x-tag',
expandBtnCls: 'x-form-trigger',
clearBtnCls: 'x-form-trigger',
listeners: {
newItem: function(bs,v, f) {bs.addItem({products: v});},
},
renderTo: Ext.getBody()
});
config.name += '[]';
modExtra.combo.Options.superclass.constructor.call(this,config);
};
Ext.extend(modExtra.combo.Options,Ext.ux.form.SuperBoxSelect);
Ext.reg('modextra-combo-options', modExtra.combo.Options);
В процессоре:<?php
class modExtraProductGetOptionsProcessor extends modObjectGetListProcessor
{
public $classKey = 'msProduct';
public $defaultSortField = 'id';
public $defaultSortDirection = 'ASC';
protected $product_id = 0;
/**
* @return bool
*/
public function initialize()
{
if ($this->getProperty('combo') && !$this->getProperty('limit') && $id = (int)$this->getProperty('id')) {
$this->product_id = $id;
}
$this->setDefaultProperties(array(
'parents' => 2,
'start' => 0,
'limit' => 20,
'sort' => $this->defaultSortField,
'dir' => $this->defaultSortDirection,
'combo' => false,
'query' => '',
));
return true;
}
/**
* @return array|string
*/
public function process()
{
$beforeQuery = $this->beforeQuery();
if ($beforeQuery !== true) {
return $this->failure($beforeQuery);
}
$data = $this->getData();
$list = $this->iterate($data);
return $this->outputArray($list, $data['total']);
}
/**
* @return array
*/
public function getData()
{
$data = array();
$limit = intval($this->getProperty('limit'));
$start = intval($this->getProperty('start'));
/* query for chunks */
$c = $this->modx->newQuery($this->classKey);
$c = $this->prepareQueryBeforeCount($c);
$data['total'] = $this->modx->getCount($this->classKey, $c);
$c = $this->prepareQueryAfterCount($c);
$sortClassKey = $this->getSortClassKey();
$sortKey = $this->modx->getSelectColumns($sortClassKey, $this->getProperty('sortAlias', $sortClassKey), '',
array($this->getProperty('sort')));
if (empty($sortKey)) {
$sortKey = $this->getProperty('sort');
}
$c->sortby($sortKey, $this->getProperty('dir'));
if ($limit > 0) {
$c->limit($limit, $start);
}
if ($c->prepare() && $c->stmt->execute()) {
$data['results'] = $c->stmt->fetchAll(PDO::FETCH_ASSOC);
}
return $data;
}
/**
* @param array $data
*
* @return array
*/
public function iterate(array $data)
{
$list = array();
$list = $this->beforeIteration($list);
$this->currentIndex = 0;
/** @var xPDOObject|modAccessibleObject $object */
foreach ($data['results'] as $array) {
$objectArray = $this->prepareResult($array);
if (!empty($objectArray) && is_array($objectArray)) {
$list[] = $objectArray;
$this->currentIndex++;
}
}
$list = $this->afterIteration($list);
return $list;
}
/**
* @param xPDOQuery $c
*
* @return xPDOQuery
*/
public function prepareQueryBeforeCount(xPDOQuery $c)
{
$c->select('id,parent,pagetitle,context_key');
$c->where(array(
'class_key' => 'msProduct',
));
if ($this->product_id) {
$c->where(array('id' => $this->product_id));
} elseif ($query = $this->getProperty('query')) {
$c->where(array('pagetitle:LIKE' => "%$query%"));
}
return $c;
}
/**
* @param array $resourceArray
*
* @return array
*/
public function prepareResult(array $resourceArray)
{
$resourceArray['parents'] = array();
$parents = $this->modx->getParentIds($resourceArray['id'], 2,
array('context' => $resourceArray['context_key']));
if ($parents[count($parents) - 1] == 0) {
unset($parents[count($parents) - 1]);
}
if (!empty($parents) && is_array($parents)) {
$q = $this->modx->newQuery('msProduct', array('id:IN' => $parents));
$q->select('id,pagetitle');
if ($q->prepare() && $q->stmt->execute()) {
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$key = array_search($row['id'], $parents);
if ($key !== false) {
$parents[$key] = $row;
}
}
}
$resourceArray['parents'] = array_reverse($parents);
}
return $resourceArray;
}
}
return 'modExtraProductGetOptionsProcessor';
И наконец в items.window.js такой код:{
xtype: 'modextra-combo-options',
fieldLabel: _('modextra_products'),
name: 'products',
id: config.id + '-products',
anchor: '99%',
allowBlank: true,
}
Здесь сам компонент github.com/SequelONE/modExtraПомогите разобраться с сохранением и выводом при редактировании.
UPD: Теперь всё сохраняется, но не отображается выбор.
Комментарии: 18
Пробовал добавить параметр
value: 'pagetitle'
не работает. Не понимаю как вывести в поле редактирования добавленные элементы. В базу они добавляются.
В базе они сохраняются в виде списка через запятую, верно?
Соответственно, нам нужно преобразовать список в массив обратно на выходе. Это делается в процессоре modObjectGetProcessor (get.class.php)
Соответственно, нам нужно преобразовать список в массив обратно на выходе. Это делается в процессоре modObjectGetProcessor (get.class.php)
public function cleanup()
{
$array = $this->object->toArray();
if(!empty($array['products'])) {
$array['products'] = explode(',', $array['products']);
}
return $this->success('', $array);
}
}
Нет, в базе сохраняется массив такого формата
["1","4","6"]
Теперь вопрос)) Уверен, что это массив?
Нет, в соседней ветке про superboxselect этот формат так назвали, по мне так это на JSON больше похоже)
В базе сохраняется такой формат как строка.
Перед сохранением нужно преобразовать массив в список.
create.class.php
update.class.php
Перед сохранением нужно преобразовать массив в список.
create.class.php
update.class.php
public function beforeSet()
{
$this->setProperty('products', implode(',', $this->getProperty('products')));
return !$this->hasErrors();
}
А для вывода, я выше написал.
В базу сохраняет NULL, если в базе сохранить
1,2,3
ничего не отображается, и поломался Grid в добавок =(
Вот get.class.php
<?php
class modExtraItemGetProcessor extends modObjectGetProcessor
{
public $objectType = 'modExtraItem';
public $classKey = 'modExtraItem';
public $languageTopics = ['modextra:default'];
//public $permission = 'view';
/**
* We doing special check of permission
* because of our objects is not an instances of modAccessibleObject
*
* @return mixed
*/
public function process()
{
if (!$this->checkPermissions()) {
return $this->failure($this->modx->lexicon('access_denied'));
}
return parent::process();
}
public function cleanup()
{
$array = $this->object->toArray();
if(!empty($array['products'])) {
$array['products'] = explode(',', $array['products']);
}
return $this->success('', $array);
}
}
return 'modExtraItemGetProcessor';
Вот create.class.php<?php
class modExtraItemCreateProcessor extends modObjectCreateProcessor
{
public $objectType = 'modExtraItem';
public $classKey = 'modExtraItem';
public $languageTopics = ['modextra'];
//public $permission = 'create';
/**
* @return bool
*/
public function beforeSet()
{
$name = trim($this->getProperty('name'));
if (empty($name)) {
$this->modx->error->addField('name', $this->modx->lexicon('modextra_item_err_name'));
} elseif ($this->modx->getCount($this->classKey, ['name' => $name])) {
$this->modx->error->addField('name', $this->modx->lexicon('modextra_item_err_ae'));
}
$this->setProperty('products', implode(',', $this->getProperty('products')));
return parent::beforeSet();
}
}
return 'modExtraItemCreateProcessor';
и update.class.php по аналогии с create.class.php<?php
class modExtraItemUpdateProcessor extends modObjectUpdateProcessor
{
public $objectType = 'modExtraItem';
public $classKey = 'modExtraItem';
public $languageTopics = ['modextra'];
//public $permission = 'save';
/**
* We doing special check of permission
* because of our objects is not an instances of modAccessibleObject
*
* @return bool|string
*/
public function beforeSave()
{
if (!$this->checkPermissions()) {
return $this->modx->lexicon('access_denied');
}
return true;
}
/**
* @return bool
*/
public function beforeSet()
{
$id = (int)$this->getProperty('id');
$name = trim($this->getProperty('name'));
if (empty($id)) {
return $this->modx->lexicon('modextra_item_err_ns');
}
if (empty($name)) {
$this->modx->error->addField('name', $this->modx->lexicon('modextra_item_err_name'));
} elseif ($this->modx->getCount($this->classKey, ['name' => $name, 'id:!=' => $id])) {
$this->modx->error->addField('name', $this->modx->lexicon('modextra_item_err_ae'));
}
$this->setProperty('products', implode(',', $this->getProperty('products')));
return parent::beforeSet();
}
}
return 'modExtraItemUpdateProcessor';
Значит ошибка в комбо
name: 'products[]',
hiddenName: 'products[]',
newItem: function(bs,v, f) {bs.addItem({pagetitle: v});},
Что-то вообще перестало в это поле сохранять. Можете посмотреть что не так github.com/SequelONE/modExtra?
Там последний коммит без этих художеств)
попробуй удалить эту строчку
config.name += '[]';
Не помогло =(
Или могу доступы дать к тестовому сайту.
Проблема так и не решилась. Видимо какой-то косяк с MODX.Window. Возможно проблема заключается в том, что выпадающий список у меня формируется из товаров miniShop2, но мне как раз необходим такой функционал. Может кто-то увидит этот комментарий и поможет разобраться?
Я так понимаю что такая же проблема?
Если да, то пока придумал только костыльное решение в виде создания плагина и в нем устанавливаю значение.
Другое решение пока не нашел, да и не искал, честно говоря.
Если да, то пока придумал только костыльное решение в виде создания плагина и в нем устанавливаю значение.
<?php
/** @var modX $modx */
switch ($modx->event->name) {
case 'OnDocFormPrerender':
if ($mode == 'upd') {
$inshop = implode(',', $resource->get('inshop'));
$modx->controller->addHtml('<script type="text/javascript">
Ext.onReady(function() {
Ext.getCmp("modx-panel-resource").getForm().setValues({"inshop[]":[' . $inshop . ']});
});
</script>');
}
}
Но у вас в окно нужно подставлять… Можно попробовать в этом плагине ловить открытие окна и подставлять.Другое решение пока не нашел, да и не искал, честно говоря.
Да, такая же. За исключением того, что я пытаюсь в компоненте modExtra это сделать в всплывающем окне при редактировании.
Ну у меня сегодня лайтовый день. Можно попробовать в скайпе созвониться… Может со второго захода получится победить эту проблему… Но не уверен… Если есть желание, то давайте скайп в личку.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.