mirror of
https://github.com/wintercms/winter.git
synced 2024-06-28 05:33:29 +02:00
Convert DataGrid form widget in to Grid widget (no longer exclusive to forms)
This commit is contained in:
parent
3c7c87b338
commit
f6fffad37d
@ -1,5 +1,6 @@
|
||||
<?php namespace Backend\FormWidgets;
|
||||
|
||||
use Backend\Widgets\Grid;
|
||||
use Backend\Classes\FormWidgetBase;
|
||||
use System\Classes\ApplicationException;
|
||||
|
||||
@ -7,15 +8,6 @@ use System\Classes\ApplicationException;
|
||||
* Grid
|
||||
* Renders a grid field.
|
||||
*
|
||||
* Supported options:
|
||||
*
|
||||
* - allowInsert
|
||||
* - autoInsertRows
|
||||
* - allowRemove
|
||||
* - allowImport
|
||||
* - allowExport
|
||||
* - exportFileName
|
||||
*
|
||||
* @package october\backend
|
||||
* @author Alexey Bobkov, Samuel Georges
|
||||
*/
|
||||
@ -26,23 +18,24 @@ class DataGrid extends FormWidgetBase
|
||||
*/
|
||||
public $defaultAlias = 'datagrid';
|
||||
|
||||
/**
|
||||
* @var array Grid columns
|
||||
*/
|
||||
protected $columns = [];
|
||||
|
||||
/**
|
||||
* @var string Grid size
|
||||
*/
|
||||
protected $size = 'large';
|
||||
|
||||
/**
|
||||
* @var Backend\Widgets\Grid Grid widget
|
||||
*/
|
||||
protected $grid;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->columns = $this->getConfig('columns', []);
|
||||
$this->size = $this->getConfig('size', $this->size);
|
||||
$this->grid = $this->makeGridWidget();
|
||||
$this->grid->bindToController();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,125 +52,10 @@ class DataGrid extends FormWidgetBase
|
||||
*/
|
||||
public function prepareVars()
|
||||
{
|
||||
$this->vars['grid'] = $this->grid;
|
||||
$this->vars['name'] = $this->formField->getName();
|
||||
$this->vars['columnHeaders'] = $this->getColumnHeaders();
|
||||
$this->vars['columnDefinitions'] = $this->getColumnDefinitions();
|
||||
$this->vars['columnWidths'] = $this->getColumnWidths();
|
||||
$this->vars['size'] = $this->size;
|
||||
$this->vars['toolbarWidget'] = $this->makeToolbarWidget();
|
||||
$this->vars['value'] = json_encode($this->model->{$this->columnName});
|
||||
}
|
||||
|
||||
protected function makeToolbarWidget()
|
||||
{
|
||||
$toolbarConfig = $this->makeConfig([
|
||||
'alias' => $this->alias . 'Toolbar',
|
||||
'buttons' => $this->getViewPath('_toolbar.htm'),
|
||||
]);
|
||||
|
||||
$toolbarWidget = $this->makeWidget('Backend\Widgets\Toolbar', $toolbarConfig);
|
||||
return $toolbarWidget;
|
||||
}
|
||||
|
||||
//
|
||||
// Getters
|
||||
//
|
||||
|
||||
protected function getColumnHeaders()
|
||||
{
|
||||
$headers = [];
|
||||
foreach ($this->columns as $key => $column) {
|
||||
$headers[] = isset($column['title']) ? $column['title'] : '???';
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
|
||||
protected function getColumnWidths()
|
||||
{
|
||||
$widths = [];
|
||||
foreach ($this->columns as $key => $column) {
|
||||
$widths[] = isset($column['width']) ? $column['width'] : '0';
|
||||
}
|
||||
return $widths;
|
||||
}
|
||||
|
||||
protected function getColumnDefinitions()
|
||||
{
|
||||
$definitions = [];
|
||||
foreach ($this->columns as $key => $column) {
|
||||
$item = [];
|
||||
$item['data'] = $key;
|
||||
|
||||
if (isset($column['readOnly']))
|
||||
$item['readOnly'] = $column['readOnly'];
|
||||
|
||||
$item = $this->evalColumnType($column, $item);
|
||||
$definitions[] = $item;
|
||||
}
|
||||
return $definitions;
|
||||
}
|
||||
|
||||
protected function evalColumnType($column, $item)
|
||||
{
|
||||
if (!isset($column['type']))
|
||||
return $item;
|
||||
|
||||
switch ($column['type']) {
|
||||
case 'number':
|
||||
$item['type'] = 'numeric';
|
||||
break;
|
||||
|
||||
case 'currency':
|
||||
$item['type'] = 'numeric';
|
||||
$item['format'] = '$0,0.00';
|
||||
break;
|
||||
|
||||
case 'checkbox':
|
||||
$item['type'] = 'checkbox';
|
||||
break;
|
||||
|
||||
case 'autocomplete':
|
||||
$item['type'] = 'autocomplete';
|
||||
if (isset($column['options'])) $item['source'] = $column['options'];
|
||||
if (isset($column['strict'])) $item['strict'] = $column['strict'];
|
||||
break;
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
//
|
||||
// AJAX
|
||||
//
|
||||
|
||||
public function onAutocomplete()
|
||||
{
|
||||
if (!$this->model->methodExists('getGridAutocompleteValues'))
|
||||
throw new ApplicationException('Model :model does not contain a method getGridAutocompleteValues()');
|
||||
|
||||
$field = post('autocomplete_field');
|
||||
$value = post('autocomplete_value');
|
||||
$data = post('autocomplete_data', []);
|
||||
$result = $this->model->getGridAutocompleteValues($field, $value, $data);
|
||||
if (!is_array($result))
|
||||
$result = [];
|
||||
|
||||
return ['result' => $result];
|
||||
}
|
||||
|
||||
//
|
||||
// Internals
|
||||
//
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadAssets()
|
||||
{
|
||||
$this->addCss('vendor/handsontable/jquery.handsontable.css', 'core');
|
||||
$this->addCss('css/datagrid.css', 'core');
|
||||
$this->addJs('vendor/handsontable/jquery.handsontable.js', 'core');
|
||||
$this->addJs('js/datagrid.js', 'core');
|
||||
$this->vars['value'] = json_encode($this->formField->value);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,4 +65,28 @@ class DataGrid extends FormWidgetBase
|
||||
{
|
||||
return json_decode($value);
|
||||
}
|
||||
|
||||
protected function makeGridWidget()
|
||||
{
|
||||
$config = $this->makeConfig((array) $this->config);
|
||||
$config->dataLocker = '#'.$this->getId('dataLocker');
|
||||
|
||||
$grid = new Grid($this->controller, $config);
|
||||
$grid->alias = $this->alias . 'Grid';
|
||||
$grid->bindEvent('grid.autocomplete', [$this, 'getAutocompleteValues']);
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function getAutocompleteValues($field, $value, $data)
|
||||
{
|
||||
if (!$this->model->methodExists('getGridAutocompleteValues'))
|
||||
throw new ApplicationException('Model :model does not contain a method getGridAutocompleteValues()');
|
||||
|
||||
$result = $this->model->getGridAutocompleteValues($field, $value, $data);
|
||||
if (!is_array($result))
|
||||
$result = [];
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -2,16 +2,7 @@
|
||||
id="<?= $this->getId() ?>"
|
||||
class="field-datagrid size-<?= $size ?>">
|
||||
|
||||
<?= $toolbarWidget->render() ?>
|
||||
|
||||
<div
|
||||
id="<?= $this->getId('grid') ?>"
|
||||
style="width:100%"
|
||||
class="control-datagrid"
|
||||
data-control="datagrid"
|
||||
data-data-locker="#<?= $this->getId('dataLocker') ?>"
|
||||
data-autocomplete-handler="<?= $this->getEventHandler('onAutocomplete') ?>"
|
||||
></div>
|
||||
<?= $grid->render() ?>
|
||||
|
||||
<input
|
||||
type="hidden"
|
||||
@ -21,9 +12,3 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$('#<?= $this->getId('grid') ?>')
|
||||
.data('columns', <?= json_encode($columnDefinitions) ?>)
|
||||
.data('columnHeaders', <?= json_encode($columnHeaders) ?>)
|
||||
.data('columnWidths', <?= json_encode($columnWidths) ?>)
|
||||
</script>
|
@ -1,6 +0,0 @@
|
||||
<div data-control="toolbar">
|
||||
<a href="#" class="btn btn-sm btn-default oc-icon-plus-square" onclick="$(this).closest('.field-datagrid').find('[data-control=datagrid]').dataGrid('insertRow')">Insert Row</a>
|
||||
<a href="#" class="btn btn-sm btn-default oc-icon-minus-square" onclick="$(this).closest('.field-datagrid').find('[data-control=datagrid]').dataGrid('removeRow')">Delete Row</a>
|
||||
<!-- <a href="#" class="btn btn-sm btn-default oc-icon-floppy-o">Save as CSV</a> -->
|
||||
<!-- <a href="#" class="btn btn-sm btn-default oc-icon-upload">Import CSV</a> -->
|
||||
</div>
|
226
modules/backend/widgets/Grid.php
Normal file
226
modules/backend/widgets/Grid.php
Normal file
@ -0,0 +1,226 @@
|
||||
<?php namespace Backend\Widgets;
|
||||
|
||||
use Backend\Classes\WidgetBase;
|
||||
|
||||
/**
|
||||
* Grid Widget
|
||||
* Renders a search container used for viewing tabular data
|
||||
*
|
||||
* Supported options:
|
||||
*
|
||||
* - allowInsert
|
||||
* - autoInsertRows
|
||||
* - allowRemove
|
||||
* - allowImport
|
||||
* - allowExport
|
||||
* - exportFileName
|
||||
*
|
||||
* @package october\backend
|
||||
* @author Alexey Bobkov, Samuel Georges
|
||||
*/
|
||||
class Grid extends WidgetBase
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public $defaultAlias = 'grid';
|
||||
|
||||
/**
|
||||
* @var array Grid columns
|
||||
*/
|
||||
protected $columns = [];
|
||||
|
||||
/**
|
||||
* @var boolean Show data table header
|
||||
*/
|
||||
protected $showHeader = true;
|
||||
|
||||
/**
|
||||
* @var boolean Insert row button
|
||||
*/
|
||||
protected $allowInsert = true;
|
||||
|
||||
/**
|
||||
* @var boolean Delete row button
|
||||
*/
|
||||
protected $allowRemove = true;
|
||||
|
||||
/**
|
||||
* @var boolean Disable the toolbar
|
||||
*/
|
||||
protected $disableToolbar = false;
|
||||
|
||||
/**
|
||||
* @var mixed Array of data, or callable for data source.
|
||||
*/
|
||||
protected $dataSource;
|
||||
|
||||
/**
|
||||
* @var string HTML element that can [re]store the grid data.
|
||||
*/
|
||||
protected $dataLocker;
|
||||
|
||||
/**
|
||||
* Initialize the widget, called by the constructor and free from its parameters.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->columns = $this->getConfig('columns', []);
|
||||
$this->showHeader = $this->getConfig('showHeader', $this->showHeader);
|
||||
$this->allowInsert = $this->getConfig('allowInsert', $this->allowInsert);
|
||||
$this->allowRemove = $this->getConfig('allowRemove', $this->allowRemove);
|
||||
$this->disableToolbar = $this->getConfig('disableToolbar', $this->disableToolbar);
|
||||
$this->dataLocker = $this->getConfig('dataLocker', $this->dataLocker);
|
||||
$this->dataSource = $this->getConfig('dataSource', $this->dataSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the widget.
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$this->prepareVars();
|
||||
return $this->makePartial('grid');
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the view data
|
||||
*/
|
||||
public function prepareVars()
|
||||
{
|
||||
$this->vars['columnHeaders'] = $this->getColumnHeaders();
|
||||
$this->vars['columnDefinitions'] = $this->getColumnDefinitions();
|
||||
$this->vars['columnWidths'] = $this->getColumnWidths();
|
||||
$this->vars['toolbarWidget'] = $this->makeToolbarWidget();
|
||||
|
||||
$this->vars['showHeader'] = $this->showHeader;
|
||||
$this->vars['allowInsert'] = $this->allowInsert;
|
||||
$this->vars['allowRemove'] = $this->allowRemove;
|
||||
$this->vars['disableToolbar'] = $this->disableToolbar;
|
||||
$this->vars['dataLocker'] = $this->dataLocker;
|
||||
}
|
||||
|
||||
protected function makeToolbarWidget()
|
||||
{
|
||||
if ($this->disableToolbar)
|
||||
return;
|
||||
|
||||
$toolbarConfig = $this->makeConfig([
|
||||
'alias' => $this->alias . 'Toolbar',
|
||||
'buttons' => $this->getViewPath('_toolbar.htm'),
|
||||
]);
|
||||
|
||||
$toolbarWidget = $this->makeWidget('Backend\Widgets\Toolbar', $toolbarConfig);
|
||||
$toolbarWidget->vars['allowInsert'] = $this->allowInsert;
|
||||
$toolbarWidget->vars['allowRemove'] = $this->allowRemove;
|
||||
return $toolbarWidget;
|
||||
}
|
||||
|
||||
//
|
||||
// AJAX
|
||||
//
|
||||
|
||||
public function onAutocomplete()
|
||||
{
|
||||
$field = post('autocomplete_field');
|
||||
$value = post('autocomplete_value');
|
||||
$data = post('autocomplete_data', []);
|
||||
$result = $this->fireEvent('grid.autocomplete', [$field, $value, $data], true);
|
||||
return ['result' => $result];
|
||||
}
|
||||
|
||||
public function onDataSource()
|
||||
{
|
||||
if ($this->dataLocker)
|
||||
return;
|
||||
|
||||
$result = $this->dataSource;
|
||||
return ['result' => $result];
|
||||
}
|
||||
|
||||
//
|
||||
// Getters
|
||||
//
|
||||
|
||||
protected function getColumnHeaders()
|
||||
{
|
||||
if (!$this->showHeader)
|
||||
return false;
|
||||
|
||||
$headers = [];
|
||||
foreach ($this->columns as $key => $column) {
|
||||
$headers[] = isset($column['title']) ? $column['title'] : '???';
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
|
||||
protected function getColumnWidths()
|
||||
{
|
||||
$widths = [];
|
||||
foreach ($this->columns as $key => $column) {
|
||||
$widths[] = isset($column['width']) ? $column['width'] : '0';
|
||||
}
|
||||
return $widths;
|
||||
}
|
||||
|
||||
protected function getColumnDefinitions()
|
||||
{
|
||||
$definitions = [];
|
||||
foreach ($this->columns as $key => $column) {
|
||||
$item = [];
|
||||
$item['data'] = $key;
|
||||
|
||||
if (isset($column['readOnly']))
|
||||
$item['readOnly'] = $column['readOnly'];
|
||||
|
||||
$item = $this->evalColumnType($column, $item);
|
||||
$definitions[] = $item;
|
||||
}
|
||||
return $definitions;
|
||||
}
|
||||
|
||||
protected function evalColumnType($column, $item)
|
||||
{
|
||||
if (!isset($column['type']))
|
||||
return $item;
|
||||
|
||||
switch ($column['type']) {
|
||||
case 'number':
|
||||
$item['type'] = 'numeric';
|
||||
break;
|
||||
|
||||
case 'currency':
|
||||
$item['type'] = 'numeric';
|
||||
$item['format'] = '$0,0.00';
|
||||
break;
|
||||
|
||||
case 'checkbox':
|
||||
$item['type'] = 'checkbox';
|
||||
break;
|
||||
|
||||
case 'autocomplete':
|
||||
$item['type'] = 'autocomplete';
|
||||
if (isset($column['options'])) $item['source'] = $column['options'];
|
||||
if (isset($column['strict'])) $item['strict'] = $column['strict'];
|
||||
break;
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
//
|
||||
// Internals
|
||||
//
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadAssets()
|
||||
{
|
||||
$this->addCss('vendor/handsontable/jquery.handsontable.css', 'core');
|
||||
$this->addCss('css/datagrid.css', 'core');
|
||||
$this->addJs('vendor/handsontable/jquery.handsontable.js', 'core');
|
||||
$this->addJs('js/datagrid.js', 'core');
|
||||
}
|
||||
|
||||
}
|
@ -83,6 +83,6 @@ class Toolbar extends WidgetBase
|
||||
if (!isset($this->config->buttons))
|
||||
return false;
|
||||
|
||||
return $this->controller->makePartial($this->config->buttons);
|
||||
return $this->controller->makePartial($this->config->buttons, $this->vars);
|
||||
}
|
||||
}
|
@ -37,12 +37,12 @@
|
||||
startRows: this.options.startRows,
|
||||
minRows: this.options.minRows,
|
||||
currentRowClassName: 'currentRow',
|
||||
// rowHeaders: true,
|
||||
// rowHeaders: false,
|
||||
// manualColumnMove: true,
|
||||
// manualRowMove: true,
|
||||
fillHandle: false,
|
||||
multiSelect: false,
|
||||
removeRowPlugin: true
|
||||
removeRowPlugin: this.options.allowRemove
|
||||
}
|
||||
|
||||
if (this.options.autoInsertRows)
|
||||
@ -68,6 +68,13 @@
|
||||
delete handsontableOptions.data
|
||||
}
|
||||
}
|
||||
else if (this.options.sourceHandler) {
|
||||
$.request(self.options.sourceHandler, {
|
||||
success: function(data, textStatus, jqXHR){
|
||||
self.gridInstance.loadData(data.result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.$el.handsontable(handsontableOptions)
|
||||
this.gridInstance = this.$el.handsontable('getInstance')
|
||||
@ -138,6 +145,8 @@
|
||||
columnWidths: null,
|
||||
columns: null,
|
||||
autocompleteHandler: null,
|
||||
sourceHandler: null,
|
||||
allowRemove: true,
|
||||
confirmMessage: 'Are you sure?'
|
||||
}
|
||||
|
23
modules/backend/widgets/grid/partials/_grid.htm
Normal file
23
modules/backend/widgets/grid/partials/_grid.htm
Normal file
@ -0,0 +1,23 @@
|
||||
<div class="datagrid-widget">
|
||||
<?php if (!$disableToolbar): ?>
|
||||
<?= $toolbarWidget->render() ?>
|
||||
<?php endif ?>
|
||||
|
||||
<div
|
||||
id="<?= $this->getId('grid') ?>"
|
||||
style="width:100%"
|
||||
class="control-datagrid"
|
||||
data-control="datagrid"
|
||||
data-allow-remove="<?= $allowRemove ? 'true' : 'false' ?>"
|
||||
<?php if ($dataLocker): ?>data-data-locker="<?= $dataLocker ?>"<?php endif ?>
|
||||
data-autocomplete-handler="<?= $this->getEventHandler('onAutocomplete') ?>"
|
||||
data-source-handler="<?= $this->getEventHandler('onDataSource') ?>"
|
||||
></div>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
$('#<?= $this->getId('grid') ?>')
|
||||
.data('columns', <?= json_encode($columnDefinitions) ?>)
|
||||
.data('columnHeaders', <?= json_encode($columnHeaders) ?>)
|
||||
.data('columnWidths', <?= json_encode($columnWidths) ?>)
|
||||
</script>
|
20
modules/backend/widgets/grid/partials/_toolbar.htm
Normal file
20
modules/backend/widgets/grid/partials/_toolbar.htm
Normal file
@ -0,0 +1,20 @@
|
||||
<div data-control="toolbar">
|
||||
<?php if ($allowInsert): ?>
|
||||
<a
|
||||
href="javascript:;"
|
||||
class="btn btn-sm btn-default oc-icon-plus-square"
|
||||
onclick="$(this).closest('.datagrid-widget').find('[data-control=datagrid]').dataGrid('insertRow')">
|
||||
Insert Row
|
||||
</a>
|
||||
<?php endif ?>
|
||||
<?php if ($allowRemove): ?>
|
||||
<a
|
||||
href="javascript:;"
|
||||
class="btn btn-sm btn-default oc-icon-minus-square"
|
||||
onclick="$(this).closest('.datagrid-widget').find('[data-control=datagrid]').dataGrid('removeRow')">
|
||||
Delete Row
|
||||
</a>
|
||||
<?php endif ?>
|
||||
<!-- <a href="#" class="btn btn-sm btn-default oc-icon-floppy-o">Save as CSV</a> -->
|
||||
<!-- <a href="#" class="btn btn-sm btn-default oc-icon-upload">Import CSV</a> -->
|
||||
</div>
|
Loading…
x
Reference in New Issue
Block a user