Обработка элемента по клику в CMP ExtJS
Здравствуйте. Есть своя табличка CMP. Данные сохраняются, обновляются с этим проблем нет. Проблема в другом. Есть строка в таблице, в строке 5 колонок, id скрыто по умолчанию (его не считаем), название (текст), урл (текст), класс ресурса (варчар), шаблон (инт) и в конце этого дела есть кнопка. Так вот, кнопку я явно сделал не правильно, мне бы такую как в минишопе в таблице заказов, где редактировать, удалить и тд. Я как бы впиперил кнопку туда, но теперь ума не приложу как заставить ее работать.
Теперь основная суть вопроса: как по клику на кнопку передать id записи таблицы в процессор в виде переменной. То есть клик, айди попал в процессоре в переменную, и дальше я уже использую эту переменную для формирования нужного запроса и тд.
Теперь основная суть вопроса: как по клику на кнопку передать id записи таблицы в процессор в виде переменной. То есть клик, айди попал в процессоре в переменную, и дальше я уже использую эту переменную для формирования нужного запроса и тд.
Комментарии: 12
так посмотрите как это сделано github.com/bezumkin/miniShop2/blob/master/assets/components/minishop2/js/mgr/orders/orders.grid.js#L113-L124
Смотрел, не могу разобраться. Я в extJS совсем зеленый.
Изучая исходники минишопа я понял что рендер для кнопок находится в js/mgr/misc/ms2.utils.js
Вот он:
Вот он:
miniShop2.utils.renderActions = function (value, props, row) {
var res = [];
var cls, icon, title, action, item = '';
for (var i in row.data.actions) {
if (!row.data.actions.hasOwnProperty(i)) {
continue;
}
var a = row.data.actions[i];
if (!a['button']) {
continue;
}
icon = a['icon'] ? a['icon'] : '';
if (typeof(a['cls']) == 'object') {
if (typeof(a['cls']['button']) != 'undefined') {
icon += ' ' + a['cls']['button'];
}
}
else {
cls = a['cls'] ? a['cls'] : '';
}
action = a['action'] ? a['action'] : '';
title = a['title'] ? a['title'] : '';
item = String.format(
'<li class="{0}"><button class="btn btn-default {1}" action="{2}" title="{3}"></button></li>',
cls, icon, action, title
);
res.push(item);
}
return String.format(
'<ul class="minishop2-row-actions">{0}</ul>',
res.join('')
);
};
Но что с ним дальше делать непонятно…
либо продолжать дальше вникать и понять что там нехватает, либо приложить код и возможно кто то подскажет что у вас не так…
У меня что-то рендер не хочет работать если его поместить в отдельный файл как в минишопе, сделал так.
Scrapx.grid.ScrapxPresets = function(config) {
config = config || {};
Ext.applyIf(config,{
id: 'scrapx-grid-scrapxpresets'
,url: Scrapx.config.connectorUrl
,baseParams: { action: 'mgr/scrapxpresets/getList' }
,fields: ['id','home_url','scrap_url','resource_class','category_id','actions']
,paging: true
,remoteSort: true
,anchor: '97%'
,autoExpandColumn: 'name'
,save_action: 'mgr/scrapxpresets/updateFromGrid'
,autosave: true
,columns: [{
header:_('scrapx.header_id')
,dataIndex: 'id'
,sortable: true
,hidden: true
},{
header:_('scrapx.header_home_url')
,dataIndex: 'home_url'
,sortable: true
,editor: {
xtype: 'textfield'
}
},{
header:_('scrapx.header_scrap_url')
,dataIndex: 'scrap_url'
,sortable: true
,editor: {
xtype: 'textfield'
}
},{
header:_('scrapx.header_resource_class')
,dataIndex: 'resource_class'
,sortable: true
,editor: {
xtype: 'modx-combo-class-derivatives'
}
,fieldLabel: _('resource_type')
,description: '<b>[[*class_key]]</b><br />'
,name: 'class_key'
,hiddenName: 'class_key'
,id: 'modx-resource-class-key'
,anchor: '100%'
},{
header:_('scrapx.header_category_id')
,dataIndex: 'category_id'
,sortable: true
,editor: {
xtype: 'numberfield'
}
},{
//header:_('scrapx.header_actions')
dataIndex: 'actions',
id: 'actions',
width: 195,
sortable: false,
fixed: true,
width: 150,
renderer: this.renderActions
}],tbar:[{
text: '<i class="icon icon-clipboard"></i> ' + _('scrapx.btn_create')
,handler: { xtype: 'scrapx-window-scrapxpresets-create' ,blankValues: true }
},'->',{
xtype: 'textfield'
,name: 'search'
,id: 'scrapx-search-filter'
,emptyText: _('scrapx.search')+'...'
,listeners: {
'change': {fn:this.search,scope:this}
,'render': {fn: function(cmp) {
new Ext.KeyMap(cmp.getEl(), {
key: Ext.EventObject.ENTER
,fn: function() {
this.fireEvent('change',this);
this.blur();
return true;
}
,scope: cmp
});
},scope:this}
}
},{
xtype: 'button'
,id: 'scrapx-filter-clear'
,text: _('scrapx.filter_clear')
,listeners: {
'click': {fn: this.clearFilter, scope: this}
}
}]
,getMenu: function() {
return [{
text: _('scrapx.menu.edit')
,handler: this.editScrapxPresets
},'-',{
text: _('scrapx.menu.remove')
,handler: this.removeScrapxPresets
}];
},editScrapxPresets: function(btn,e) {
if (!this.editScrapxPresetsWindow) {
this.editScrapxPresetsWindow = MODx.load({
xtype: 'scrapx-window-scrapxpresets-edit'
,record: this.menu.record
,listeners: {
'success': {fn:this.refresh,scope:this}
}
});
}
this.editScrapxPresetsWindow.setValues(this.menu.record);
this.editScrapxPresetsWindow.show(e.target);
},removeScrapxPresets: function() {
MODx.msg.confirm({
title: _('scrapx.title.win_remove')
,text: _('scrapx.confirm.remove')
,url: this.config.url
,params: {
action: 'mgr/scrapxpresets/remove'
,id: this.menu.record.id
}
,listeners: {
'success': {fn:this.refresh,scope:this}
}
});
}
});
Scrapx.grid.ScrapxPresets.superclass.constructor.call(this,config)
};
Ext.extend(Scrapx.grid.ScrapxPresets,MODx.grid.Grid,{
search: function(tf,nv,ov) {
var s = this.getStore();
s.baseParams.query = tf.getValue();
this.getBottomToolbar().changePage(1);
this.refresh();
}
,clearFilter: function() {
var s = this.getStore();
s.baseParams.search = '';
Ext.getCmp('scrapx-search-filter').reset();
this.getBottomToolbar().changePage(1);
this.refresh();
},
renderActions: function (value, props, row) {
var res = [];
var cls, icon, title, action, item;
if (typeof(value) == 'object') {
for (var i in value) {
if (!value.hasOwnProperty(i)) {
continue;
}
var a = value[i];
if (!a['button']) {
continue;
}
icon = a['icon'] ? a['icon'] : '';
if (typeof(a['cls']) == 'object') {
if (typeof(a['cls']['button']) != 'undefined') {
icon += ' ' + a['cls']['button'];
}
} else {
cls = a['cls'] ? a['cls'] : '';
}
action = a['action'] ? a['action'] : '';
title = a['title'] ? a['title'] : '';
item = String.format(
'<li class="{0}"><button class="btn btn-default {1}" action="{2}" title="{3}"></button></li>',
cls, icon, action, title
);
res.push(item);
}
}
return String.format(
'<ul class="xp-row-actions">{0}</ul>',
res.join('')
);
}
});
Ext.reg('scrapx-grid-scrapxpresets',Scrapx.grid.ScrapxPresets);
Scrapx.window.EditScrapxPresets = function(config) {
config = config || {};
var self = this;
Ext.applyIf(config,{
title: _('scrapx.title.win_edit')
,url: Scrapx.config.connectorUrl
,autoHeight: true
,modal: true
,baseParams: {
action: 'mgr/scrapxpresets/update'
}
,fields: [{
xtype: 'hidden'
,name: 'id'
},{
xtype: 'textarea'
,fieldLabel: _('scrapx.label_home_url')
,description: '<b>[[*home_url]]</b><br />'+_('scrapx.label_home_url_help')
,name: 'home_url'
,allowBlank:false
,anchor: '100%'
},{
xtype: 'textarea'
,fieldLabel: _('scrapx.label_scrap_url')
,description: '<b>[[*scrap_url]]</b><br />'+_('scrapx.label_scrap_url_help')
,name: 'scrap_url'
,allowBlank:false
,anchor: '100%'
},{
xtype: 'textfield'
,fieldLabel: _('scrapx.label_resource_class')
,description: '<b>[[*resource_class]]</b><br />'+_('scrapx.label_resource_class_help')
,name: 'resource_class'
,allowBlank:false
,anchor: '100%'
},{
xtype: 'numberfield'
,fieldLabel: _('scrapx.label_category_id')
,description: '<b>[[*category_id]]</b><br />'+_('scrapx.label_category_id_help')
,name: 'category_id'
,allowBlank:false
,anchor: '100%'
}]
});
Scrapx.window.EditScrapxPresets.superclass.constructor.call(this,config);
};
Ext.extend(Scrapx.window.EditScrapxPresets,MODx.Window,{});
Ext.reg('scrapx-window-scrapxpresets-edit',Scrapx.window.EditScrapxPresets);
Scrapx.window.CreateScrapxPresets = function(config) {
config = config || {};
var self = this;
Ext.applyIf(config,{
title: _('scrapx.title.win_create')
,url: Scrapx.config.connectorUrl
,autoHeight:true
,modal: true
,baseParams: {
action: 'mgr/scrapxpresets/create'
}
,fields: [{
xtype: 'hidden'
,name: 'id'
},{
xtype: 'textarea'
,fieldLabel: _('scrapx.label_home_url')
,description: '<b>[[*home_url]]</b><br />'+_('scrapx.label_home_url_help')
,name: 'home_url'
,allowBlank:false
,anchor: '100%'
},{
xtype: 'textarea'
,fieldLabel: _('scrapx.label_scrap_url')
,description: '<b>[[*scrap_url]]</b><br />'+_('scrapx.label_scrap_url_help')
,name: 'scrap_url'
,allowBlank:false
,anchor: '100%'
},{
xtype: 'textfield'
,fieldLabel: _('scrapx.label_resource_class')
,description: '<b>[[*resource_class]]</b><br />'+_('scrapx.label_resource_class_help')
,name: 'resource_class'
,allowBlank:false
,anchor: '100%'
},{
xtype: 'numberfield'
,fieldLabel: _('scrapx.label_category_id')
,description: '<b>[[*category_id]]</b><br />'+_('scrapx.label_category_id_help')
,name: 'category_id'
,allowBlank:false
,anchor: '100%'
}]
});
Scrapx.window.CreateScrapxPresets.superclass.constructor.call(this,config);
};
Ext.extend(Scrapx.window.CreateScrapxPresets,MODx.Window);
Ext.reg('scrapx-window-scrapxpresets-create',Scrapx.window.CreateScrapxPresets);
Обертка для кнопок появляется в разметке, а вот кнопок нет. Значит их надо откуда-то передать. Смотрим getList процессор минишопа, там есть вот такая функция:/**
* @param array $data
*
* @return array
*/
public function prepareArray(array $data)
{
if (empty($data['customer'])) {
$data['customer'] = $data['customer_username'];
}
$data['status'] = '<span style="color:#' . $data['color'] . ';">' . $data['status'] . '</span>';
unset($data['color']);
if (isset($data['cost'])) {
$data['cost'] = $this->ms2->formatPrice($data['cost']);
}
if (isset($data['cart_cost'])) {
$data['cart_cost'] = $this->ms2->formatPrice($data['cart_cost']);
}
if (isset($data['delivery_cost'])) {
$data['delivery_cost'] = $this->ms2->formatPrice($data['delivery_cost']);
}
if (isset($data['weight'])) {
$data['weight'] = $this->ms2->formatWeight($data['weight']);
}
$data['actions'] = array(
array(
'cls' => '',
'icon' => 'icon icon-edit',
'title' => $this->modx->lexicon('ms2_menu_update'),
'action' => 'updateOrder',
'button' => true,
'menu' => true,
),
array(
'cls' => array(
'menu' => 'red',
'button' => 'red',
),
'icon' => 'icon icon-trash-o',
'title' => $this->modx->lexicon('ms2_menu_remove'),
'multiple' => $this->modx->lexicon('ms2_menu_remove_multiple'),
'action' => 'removeOrder',
'button' => true,
'menu' => true,
),
/*
array(
'cls' => '',
'icon' => 'icon icon-cog actions-menu',
'menu' => false,
'button' => true,
'action' => 'showMenu',
'type' => 'menu',
),
*/
);
return $data;
}
Вот это нас не интересует:if (empty($data['customer'])) {
$data['customer'] = $data['customer_username'];
}
$data['status'] = '<span style="color:#' . $data['color'] . ';">' . $data['status'] . '</span>';
unset($data['color']);
if (isset($data['cost'])) {
$data['cost'] = $this->ms2->formatPrice($data['cost']);
}
if (isset($data['cart_cost'])) {
$data['cart_cost'] = $this->ms2->formatPrice($data['cart_cost']);
}
if (isset($data['delivery_cost'])) {
$data['delivery_cost'] = $this->ms2->formatPrice($data['delivery_cost']);
}
if (isset($data['weight'])) {
$data['weight'] = $this->ms2->formatWeight($data['weight']);
}
Значит оставляем примерно так:/**
* @param array $data
*
* @return array
*/
public function prepareArray(array $data){
$data['actions'] = array(
array(
'cls' => '',
'icon' => 'icon icon-edit',
'title' => $this->modx->lexicon('scrapx.action_parse'),
'action' => 'getScraping',
'button' => true,
'menu' => true,
),
);
return $data;
}
Но вот это $data['actions'] тоже надо откуда то взять в процессоре… Блин как все запутано. Может я вообще нет так делаю?:)
Вот здесь происходит распознавание клика по таблице.
Туда прилетают любые клики, а дальше идёт проверка, по какому именно месту кликнули. Если это кнопка или ссылка — то идёт работа. Если нет, то событие пропускается дальше.
Это — основная таблица элементов miniShop2, от неё наследуются все остальные, поэтому ты и не нашёл этот обработчик.
Туда прилетают любые клики, а дальше идёт проверка, по какому именно месту кликнули. Если это кнопка или ссылка — то идёт работа. Если нет, то событие пропускается дальше.
Это — основная таблица элементов miniShop2, от неё наследуются все остальные, поэтому ты и не нашёл этот обработчик.
Спасибо за совет. Я уже «вкурил» что есть основная таблица defaul.grid.js а от нее наследуется order.grid.js. Сложно так вот сразу понять схему работы всего этого дела. Также понял как работает вот это из отдельного файла:
В вашем файле core/componenets/minishop2/processors/mgr/orders/getlist.php есть такая функция, которая как мне показалось отвечает за вызов собственно кнопок действий:
В месте где должны быть кнопки в таблице у меня выводится обертка
miniShop2.utils.renderActions = function (value, props, row) {
var res = [];
var cls, icon, title, action, item = '';
for (var i in row.data.actions) {
if (!row.data.actions.hasOwnProperty(i)) {
continue;
}
var a = row.data.actions[i];
if (!a['button']) {
continue;
}
icon = a['icon'] ? a['icon'] : '';
if (typeof(a['cls']) == 'object') {
if (typeof(a['cls']['button']) != 'undefined') {
icon += ' ' + a['cls']['button'];
}
}
else {
cls = a['cls'] ? a['cls'] : '';
}
action = a['action'] ? a['action'] : '';
title = a['title'] ? a['title'] : '';
item = String.format(
'<li class="{0}"><button class="btn btn-default {1}" action="{2}" title="{3}"></button></li>',
cls, icon, action, title
);
res.push(item);
}
return String.format(
'<ul class="minishop2-row-actions">{0}</ul>',
res.join('')
);
};
То есть надо написать так (ну это я так понял, может и не так):Ext.namespace('Scrapx.utils'); // вот это я так понимаю указывает что мы расширяем пространство имен
// и тут уже можно писать рендерер
Scrapx.utils.renderActions = function (value, props, row) {
var res = [];
var cls, icon, title, action, item = '';
for (var i in row.data.actions) {
if (!row.data.actions.hasOwnProperty(i)) {
continue;
}
var a = row.data.actions[i];
if (!a['button']) {
continue;
}
icon = a['icon'] ? a['icon'] : '';
if (typeof(a['cls']) == 'object') {
if (typeof(a['cls']['button']) != 'undefined') {
icon += ' ' + a['cls']['button'];
}
}
else {
cls = a['cls'] ? a['cls'] : '';
}
action = a['action'] ? a['action'] : '';
title = a['title'] ? a['title'] : '';
item = String.format(
'<li class="{0}"><button class="btn btn-default {1}" action="{2}" title="{3}"></button></li>',
cls, icon, action, title
);
res.push(item);
}
return String.format(
'<ul class="minishop2-row-actions">{0}</ul>',
res.join('')
);
};
Добавляем в файле core/components/scrapx/controllers/default/scrapxpresets.class.php:$this->addJavascript($this->scrapx->config['jsUrl'].'mgr/widgets/utils.js');
Теперь я вызываю у себя в файле assets/components/scrapx/js/mgr/widgets/scrapxpresets.grid.js рендерер вот так:{
header:_('scrapx.header_actions')
,dataIndex: 'actions'
,sortable: true
,renderer: Scrapx.utils.renderActions
}
И он работает.В вашем файле core/componenets/minishop2/processors/mgr/orders/getlist.php есть такая функция, которая как мне показалось отвечает за вызов собственно кнопок действий:
public function prepareArray(array $data)
{
if (empty($data['customer'])) {
$data['customer'] = $data['customer_username'];
}
$data['status'] = '<span style="color:#' . $data['color'] . ';">' . $data['status'] . '</span>';
unset($data['color']);
if (isset($data['cost'])) {
$data['cost'] = $this->ms2->formatPrice($data['cost']);
}
if (isset($data['cart_cost'])) {
$data['cart_cost'] = $this->ms2->formatPrice($data['cart_cost']);
}
if (isset($data['delivery_cost'])) {
$data['delivery_cost'] = $this->ms2->formatPrice($data['delivery_cost']);
}
if (isset($data['weight'])) {
$data['weight'] = $this->ms2->formatWeight($data['weight']);
}
$data['actions'] = array(
array(
'cls' => '',
'icon' => 'icon icon-edit',
'title' => $this->modx->lexicon('ms2_menu_update'),
'action' => 'updateOrder',
'button' => true,
'menu' => true,
),
array(
'cls' => array(
'menu' => 'red',
'button' => 'red',
),
'icon' => 'icon icon-trash-o',
'title' => $this->modx->lexicon('ms2_menu_remove'),
'multiple' => $this->modx->lexicon('ms2_menu_remove_multiple'),
'action' => 'removeOrder',
'button' => true,
'menu' => true,
),
/*
array(
'cls' => '',
'icon' => 'icon icon-cog actions-menu',
'menu' => false,
'button' => true,
'action' => 'showMenu',
'type' => 'menu',
),
*/
);
return $data;
}
Я у себя в файле core/components/scrapx/processors/mgr/scrapxpresets/getlist.class.php добавил вот так:<?php
class ScrapxPresetsGetListProcessor extends modObjectGetListProcessor {
public $languageTopics = array('scrapx:scrapxpresets');
public $classKey = 'ScrapxPresets';
public $defaultSortField = 'id';
public $defaultSortDirection = 'ASC';
public $checkListPermission = true;
public function prepareQueryBeforeCount(xPDOQuery $c) {
$query = $this->getProperty('query');
if (!empty($query)) {
$c->where(array('name:LIKE' => '%'.$query.'%'));
}
return $c;
}
/**
* @param array $data
*
* @return array
*/
public function prepareArray(array $data){
$data['actions'] = array(
array(
'cls' => '',
'icon' => 'icon icon-edit',
'title' => $this->modx->lexicon('scrapx.scrapping'),
'action' => 'scrapping',
'button' => true,
'menu' => true,
),
);
return $data;
}
}
return 'ScrapxPresetsGetListProcessor';
Но никакие кнопки в таблице пока не появились. Пока не разобрался что делать дальше.В месте где должны быть кнопки в таблице у меня выводится обертка
<ul class="minishop2-row-actions"></ul>
Но пунктов никаких нет. Вот теперь думаю как передать правильно туда данные… вообще не пойму пока что делать дальше. Изучаю ваши исходники минишопа и экспериментирую методом тыка…
Да нахрена ж ты копируешь эти километровые куски кода?
Даже читать не буду, разбирайся дальше сам.
Даже читать не буду, разбирайся дальше сам.
Спасибо, разберусь. Нахрена код копирую? Ну вы же не экстрасенс чтобы знать что я там понаписал. Или лучше на пальцах объяснять? Ну вам виднее.
Обратите внимание на метод prepareArray, который вы используете в процессоре GetList. Он нигде не прописан у вас. У Василия же вот тут.
Спасибо большое за подсказку. Что то я это место упустил из виду. Надо попробовать. Не подскажете какая функция в extJs подхватывает $data? Это не оно Scrapx.utils.renderActions = function…?
Разобрался самостоятельно, все что хотел сделал. Всем спасибо за ответы.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.