Id Name Link Inserted Img Status
One 6r0xliyalt 6. 2. 2015 Id = 1, img = img-1
2.00 ozl4gy9udu 6. 2. 2015 Id = 2, img = img-2
3.00 9i20xsrese 6. 2. 2015 Id = 3, img = img-3
4.00 yk95ak88ra 6. 2. 2015 Id = 4, img = img-4
5.00 2loxs05egs 6. 2. 2015 Id = 5, img = img-5
6.00 wzrdlu2o0v 6. 2. 2015 Id = 6, img = img-6
7.00 401nd5xv80 6. 2. 2015 Id = 7, img = img-7
8.00 qeba0t2ovv 6. 2. 2015 Id = 8, img = img-8
9.00 el25id2emd 6. 2. 2015 Id = 9, img = img-9
Ten vmkppicf1z 6. 2. 2015 Id = 10, img = img-10
Summary renderer: 55 $
( Items: 1 - 10 from 200 )

Show me the code of this datagrid

public function createComponentColumnsGrid($name)
{
	/**
	 * @var Ublaboo\DataGrid\DataGrid
	 */
	$grid = new DataGrid($this, $name);

	$grid->setDataSource($this->ndb->table('ublaboo_example'));

	$grid->setColumnsHideable();
	$grid->setMultiSortEnabled();

	$grid->addColumnNumber('id', 'Id')
		->setSortable()
		->setFormat(2)
		->setAlign('left')
		->setReplacement([1 => 'One', 10 => 'Ten']);

	$grid->setColumnsSummary(['id'])
		->setRenderer(function(int $summary, string $column): string {
			return 'Summary renderer: ' . $summary . ' $';
		});

	$grid->addColumnText('name', 'Name')
		->setSortable()
		->setSortableResetPagination();

	$grid->addColumnLink('link', 'Link', 'this#demo', 'name', ['id', 'surname' => 'name']);

	$grid->addColumnDateTime('inserted', 'Inserted');

	$grid->addColumnText('img', 'Img')
		->setTemplate(__DIR__ . '/templates/Datagrid/grid.img.latte');

	$grid->addColumnStatus('status', 'Status')
		/*->setCaret(FALSE)*/
		->addOption(1, 'Online')
			/*->setIcon('check')*/
			->setClass('btn-success')
			->endOption()
		->addOption(2, 'Standby')
			/*->setIcon('user')*/
			->setClass('btn-primary')
			->endOption()
		->addOption(0, 'Offline')
			/*->setIcon('close')*/
			->setClass('btn-danger')
			->endOption()
		->onChange[] = [$this, 'statusChange'];

	$grid->addColumnCallback('link', function($column, $item) {
		if ($item->id == 2) {
			$column->setRenderer(function() {
				return '';
			});
		}
	});
}


public function statusChange($id, $new_status)
{
	if (in_array($new_status, [0, 1, 2])) {
		$this->ndb->table('ublaboo_example')
			->where('id = ?', $id)
			->update(['status' => $new_status]);
	}

	$status_text = ['offline', 'online', 'standby'][$new_status];

	$this->flashMessage("Status of category [$id] was updated to [$status_text].", 'success');

	if ($this->isAjax()) {
		$this->redrawControl('flashes');
		$this['columnsGrid']->redrawItem($id);
	}
}

And the template grid.img.latte:

Id = {$item->id}, 
img = <img src="{$basePath}/assets/images/social/_github_black.png" style="height: 17px;">

Column

There are several column classes and they all have some common behaviour and properties.

Api

Parameters

Lets add a simple text column like we've done before:

$grid->addColumnText('name', 'Name');

Parameters that the method takes are: $key, $title, $column = $key. By default, the column name is the same as the key. There is a key, because you can show more data grid columns that will display only one database table column:

$grid->addColumnText('name', 'Name'); // Equivalent to $grid->addColumnText('name', 'Name', 'name');
$grid->addColumnText('name2', 'Name', 'name');
$grid->addColumnText('name3', 'Name', 'name');

Templates

Column may have it's own template. I will add one more parameter (optional) to the method ::setTemplate(), just for fun:

$grid->addColumnText('name', 'Name')
	->setTemplate(__DIR__ . '/templates/name.latte', ['foo' => 'bar']);

In that template (name.latte), we will have two variables available: $item and $foo. The parameter (expanded array) is there just in case you need it sometime.

There is another way to set column templates in just one file, but that will be described in other chapter.

Renderers

We can also modify data outputting via renderer callbacks:

$grid->addColumnText('name', 'Name')
	->setRenderer(function($item) {
		return strtoupper($item->id . ': ' . $item->name);
	});

But hey, what if i want to replace just some rows? No problem, the second optional argument tells me (callback again) whether the datagrid should use your renderer or not. Example:

$grid->addColumnText('name', 'Name')
	->setRenderer(function($item) {
		return strtoupper($item->id . ': ' . $item->name);
	}, function($item) {
		return (bool) ($item->id % 2);
	});

Replacement

Outputted data could have a simple array replacement instead of renderer callback:

$grid->addColumnText('name', 'Name')
	->setReplacement([
		'John' => 'Doe',
		'Hell' => 'o'
	]);

Escaping values

By default, latte escapes all values from datasource. You can disable that:

$grid->addColumnText('link_html', 'Link')
	->setTemplateEscaping(FALSE);

Sorting

You can set the column as sortable.

$grid->addColumnText('name', 'Name')
	->setSortable();

When using doctrine as data source, you can output data the object way using dot-notaion and property accessor. But when you are using collumn of related table for sorting, you probably want to use alias for sorting:

$grid->addColumnText('role', 'User role', 'role.name')
	->setSortable('r.name')

Resetting pagination after sorting

$grid->addColumnText('name', 'Name')
	->setSortable()
	->setSortableResetPagination();

Default sort

DataGrid implements default sorting mechanism:

$grid->setDefaultSort(['name' => 'DESC']);

Resetting default sort

By default, once you reset the filter, default sort is applied. If you don't want to apply it after resetting the filter, pass FALSE as a second parameter to DataGrid::setDefaultSort():

$grid->setDefaultSort('id' => 'DESC', FALSE);

Multiple columns sort

Sorting by multiple columns is disabled by default. But can be enaled:

$grid->setMultiSortEnabled($enabled = TRUE); // Pass FALSE to disable

Default per page

You can also set default "items per page" value:

$grid->setDefaultPerPage(20);

Custom sorting Callback

You can define your own sorting callback:

$grid->addColumnText('name', 'Name')
	->setSortable()
	->setSortableCallback(function($datasource, $sort) {
		/**
		 * Apply your sorting...
		 * 	(e.g. $sort = ['name' => 'ASC'])
		 */
	});

Align

Column can be aligned to one side:

$grid->addColumnText('name', 'Name')
	->setAlign('center');

Removing column

You can remove column from grid like so:

$grid->addColumnText('foo', 'Name', 'name');
$grid->removeColumn('foo');

Column Text

We have discussed this in examples above - it's pretty basic column.

Column Number

What more can ColumnNumber offer? Number formatting:

/**
 * Default format: decimals = 0, dec_point = '.', thousands_sep = ' '
 */
$grid->addColumnNumber('price', 'Price');
$grid->addColumnNumber('price2', 'Price', 'price')
	->setFormat(2, ',', '.');

Column DateTime

DateTime formatting (or just date or just time):

/**
 * Default format: 'j. n. Y'
 */
$grid->addColumnDateTime('created', 'Date registered')
	->setFormat('H:i:s');

We can use column link to output <a> element:

/**
 * Parameters order: $key, $name, $href = NULL, $column = NULL, array $params = NULL
 */
$grid->addColumnLink('name', 'Name', 'edit');

Now, ColumnLink is pretty clever! It passes an id parameter to the "edit" destination. Well, not id, more likely $primary_key, which can be changed.

But that is not all. What if we want to pass some other parameters to the action method (or handler - edit!)? Use the last method parameter:

$grid->addColumnLink('name', 'Name', 'edit', 'name', ['role']);

That is still not all. You can pass the parameters under different name:

$grid->addColumnLink('name', 'Name', 'edit', 'name', ['id', 'surname' => 'name']);

Now, suppose the row in database with name = John and id = 5. Then the link will look something like that: /edit?id=5&surname=John!

Open in new tab

You can tell ColumnLink to open its link in new tab:

$grid->addColumnLink('name', 'Name', 'edit')
	->setOpenInNewTab();

Column Status

Status 1 Status 2

Once your item keep some "status" flag, it is appropriate to show user the status in highlighted form. Also there could be a dropdown with available statuses:

$grid->addColumnStatus('status', 'Status')
	->addOption(1, 'Online')
		->endOption()
	->addOption(0, 'Offline')
		->endOption()
	->onChange[] = function($id, $new_value) { dump($id, $new_value); die; };

ColumnStatus has optional caret, icon and class. By default, there is a caret visible and the main button that toggles statuses dropdown has class "btn-success". You can change all these properties:

$grid->addColumnStatus('status', 'Status')
	->setCaret(FALSE)
	->addOption(1, 'Online')
		->setIcon('check')
		->setClass('btn-success')
		->endOption()
	->addOption(2, 'Standby')
		->setIcon('user')
		->setClass('btn-primary')
		->endOption()
	->addOption(0, 'Offline')
		->setIcon('close')
		->setClass('btn-danger')
		->endOption()
	->onChange[] = [$this, 'statusChange'];

There are 2 default class properties in Option. $class = 'btn-success' and $class_secondary = 'ajax btn btn-default btn-xs'. As you can see, the default request is called via ajax. You can of course change that ($option->setClassSecondary('btn btn-default')).

When ajax request changeStatus! is called, you probably want to redraw the item after changing item status:

public function createComponentColumnsGrid($name)
{
	$grid->addColumnStatus('status', 'Status')
		# ...
		->onChange[] = [$this, 'statusChange'];
}


public function statusChange($id, $new_status)
{
	# ...

	if ($this->isAjax()) {
		$this['columnsGrid']->redrawItem($id);
	}
}

Also, option classes in dropdown can be altered:

$grid->addColumnStatus('status', 'Status')
	->addOption(1, 'Online')
	->setClassInDropdown('foo');

Options could be also set at once:

$grid->addColumnStatus('status', 'Status')
	->setOptions([1 => 'Online', 2 => 'Standby'])

Accessing particular option:

$grid->getColumn('status')->getOption(2)
	->setClass('btn-primary'); // For example

Hideable columns

Columns Hiding

In example datargid above, you can hide columns and then reveal them again. This feature is disabled by default. You can enable it like this:

$grid->setColumnsHideable();

Hidden columns are saved into session, so they will remain hidden along all next requests.

Default hide

Columns can be hidden by default:

$grid->addColumnText('name', 'Name')
	->setDefaultHide(); // Or disable default hide: ::setDefaultHide(FALSE)

If default hide is used, new button is shown in that settings (gear) dropdown - Show default columns:

Columns Summary

Datagrid implements a feature that allows you to display sum of column of displayed items at the bootom of the grid. Try it out:

$grid->addColumnNumber('in', 'Income')
	->setFormat(2, ',', '.');

$grid->addColumnNumber('out', 'Expenses')
	->setFormat(2, ',', '.');

$grid->setColumnsSummary(['in', 'out']);

Summary will be aligned to the same site as the column it is counting. By default, number format is taken also from it's column, but you can change the formatting (for each sum separately):

$grid->setColumnsSummary(['in', 'out'])
	->setFormat('out', 0, '.', ' ');

Sure you can use your own callback for each row item number to be add to summary:

$grid->setColumnsSummary(['id'], function($item, $column) {
	return $item->{$column} * 10;
});

And as many other places, you may want to use your own renderer callback to show user altered summary data:

$grid->setColumnsSummary(['price', 'amount'])
	->setRenderer(function($sum, string $column): string {
		if ($column === 'price') {
			return $sum . ' $';
		}

		return $sum . ' items';
	});

Column (<th>, <td>) attributes

Since table cell elements are rendered using Nette\Utils\Html, you can easily alter their html attributes (class, data-attributes etc):

$th = $grid->addColumnText('name', 'Name')
    ->getElementPrototype('td'); // Or element element <th> via Column::getElementPrototype('th')

$th->data('foo', 'bar');
$th->class('super-column')

If you want to modify attributes for both <th> and <td> at one time, use directly Column::addAttributes():

$grid->addColumnText('name', 'Name')
    ->addAttributes(['class' => 'text-center']);

Column callback

When you need to modify columns just before rendering (meybe remove some status options or completely change renderer for partucular items), you can create column callback, that will be called with $column and $item in parameter:

$grid->addColumnLink('link', 'Link', 'this#demo', 'name', ['id', 'surname' => 'name']);

$grid->addColumnStatus('status', 'Status')
	->addOption(1, 'Online')
		->setClass('btn-success')
		->endOption()
	->addOption(2, 'Standby')
		->setClass('btn-primary')
		->endOption()
	->addOption(0, 'Offline')
		->setClass('btn-danger')
		->endOption()
	->onChange[] = [$this, 'changeStatus'];

$grid->addColumnCallback('status', function($column, $item) {
	if ($item->id == 2) {
		$column->removeOption(2);
	}
});

$grid->addColumnCallback('link', function($column, $item) {
	if ($item->id == 2) {
		$column->setRenderer(function() {
			return '';
		});
	}
});

That is the code of the demove shown above. As you can see, item with id == 1 does have a empty link column and only 2 options in ColumnSatus.

If you want to overwrite whole ColumnStatus template rendering, you have to remove the template first:

$grid->addColumnCallback('status', function($column, $item) {
	if ($item->id == 2) {
		$column->setTemplate(NULL);
		$column->setRenderer(function() {
			return 'My super another status';
		});
	}
});
Tento web používá k poskytování služeb a analýze návštěvnosti soubory cookie. Používáním tohoto webu s tím souhlasíte. V pořádku Další informace