Id Name Random string Inserted Action
1 6r0xliyalt yrgwlxn8cedwk4fliqkdf1uez6di4s1m1xjvfs6u8mwc0sm07c 6. 2. 2015 Blahblah
2 ozl4gy9udu m3t9jpx6qn25bp0v96ra1y2mn9nnnrorv15pi6qvfyd0341on6 6. 2. 2015 Blahblah
3 9i20xsrese hwqw76zqx8odf48hd6prw0iyss6p9i6xllw21dvlcp8fhnkasl 6. 2. 2015 Blahblah
4 yk95ak88ra 168ddj44k9xth4uqtfsjlyf83zd2dqhnku6a4nuwj3xohjlp9g 6. 2. 2015 Blahblah
5 2loxs05egs owyjm8fg6g9h7hnav6llbmmnhslk5vki7lbquxm1kotz76wxyt 6. 2. 2015 Blahblah
6 wzrdlu2o0v 6bqajl5x9mjen6b0c3no5xn98aarl9wrvjpre4cqdti70dyx31 6. 2. 2015 Blahblah
7 401nd5xv80 pizteygp3k0njs4wpl00qt382jflpcjnfifn4spdpsyrgm9qg2 6. 2. 2015 Blahblah
8 qeba0t2ovv nbe6u5jr85ki7u22x78lfaalyc7gua19xwegdqier2mzovse8n 6. 2. 2015 Blahblah
9 el25id2emd md500y2uvgzjpayse164gfbjhywvvyaguz4ix07fknboe26cdx 6. 2. 2015 Blahblah
10 vmkppicf1z q16ic7ea5uydevcp5km6rqm8adw6de0m4gckpdnqeej6hoxh6c 6. 2. 2015 Blahblah
( Items: 1 - 10 from 200 )

Show me the code of this datagrid

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

	$grid->setSortable();

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

	/**
	 * Columns
	 */
	$grid->addColumnNumber('id', 'Id')
		->setAlign('left')
		->setSortable();

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

	$grid->addColumnText('random', 'Random string')
		->setRenderer(function() {
			return Nette\Utils\Random::generate(50);
		});

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

	/**
	 * MultiAction
	 */
	$grid->addMultiAction('multi_blah', 'MultiAction')
		->addAction('blah', 'Blahblah', 'blah!')
		->addAction('blah2', 'Blahblah2', 'blah!', ['name']);

	$grid->getAction('multi_blah')
		->getAction('blah2')->setIcon('check');

	/**
	 * Actions
	 */
	$grid->addAction('blah', 'Blahblah', 'blah!')
		->setClass('btn btn-xs btn-primary ajax');

	$grid->addAction('this', '')
		->setIcon('repeat')
		->setClass('btn btn-xs btn-success');

	$grid->addAction('icon', 'Delitelne 3')
		->setTemplate(__DIR__ . '/templates/Datagrid/icon.latte', ['']);

	$grid->addActionCallback('custom_callback', '')
		->setIcon('sun-o')
		->setTitle('Hello, sun')
		->setClass('btn btn-xs btn-default ajax')
		->onClick[] = function($item_id) {
			$this->flashMessage('Custom callback triggered, id: ' . $item_id);
			$this->redrawControl('flashes');
		};

	$grid->addAction('delete', '', 'delete!')
		->setIcon('trash')
		->setTitle('Delete')
		->setClass('btn btn-xs btn-danger ajax')
		->setConfirm('Do you really want to delete example %s?', 'name');

	/**
	 * ToolbarButtons
	 */
	$grid->addToolbarButton('this', 'Toolbar')->addAttributes(['foo' => 'bar']);
	$grid->addToolbarButton('this2', 'Button', ['foo' => 'bar']);

	$grid->setItemsPerPageList([10,50, 100, 9999]);
}

Action

Api

Parameters

Parameters are the same as in ColumnLink:

/**
 * $key, $name = '', $href = $key, array $params = NULL
 */
$grid->addAction('edit', 'Edit');

Icon

$grid->addAction('edit', '')
	->setIcon('pencil');

Action icon can be defined by your callback. Row $item is passed to your callback as the only argument.

$grid->addAction('send', '')
	->setIcon(function($item) { return $item->sent_already ? 'repeat' : 'envelope'; });

Class

$grid->addAction('dosth', '', 'doSomething!')
	->setIcon('pencil')
	->setClass('btn btn-xs btn-danger ajax');

Action class can be also defined by your callback. Row $item is passed to your callback as the only argument.

$grid->addAction('send', '')
	->setIcon('envelope')
	->setClass(function($item) { return $item->sent_already ? 'btn btn-xs btn-success' : 'btn btn-xs btn-default' });

Title

$grid->addAction('edit', '')
	->setIcon('pencil')
	->setTitle('Edit row');

Action title can be defined by custom callback same as title or class.

Confirmation

$grid->addAction('delete', '', 'delete!')
	->setIcon('trash')
	->setTitle('Smazat')
	->setClass('btn btn-xs btn-danger ajax')
	->setConfirm('Do you really want to delete row %s?', 'name'); // Second parameter is optional

If you want to define confirmation dialog with a callback, the callback has to return string. It can optionally return string containing %s placeholder. In that case you should provide column name as the second argument to ::setConfirm() method.

$grid->addAction('delete', '', 'delete!')
	->setConfirm(function($item) {
		return 'Do you really want to delete row with id ' . $item->id . ' and name %s?';
	}, 'name');

/**
 * Same result
 */
$grid->addAction('delete', '', 'delete!')
	->setConfirm(function($item) {
		return 'Do you really want to delete row with id ' . $item->id . ' and name ' . $item->name . '?';
	});

Ajax

Redrawing the data

All links are by default not-ajax. Do you see the bold ajax class in previous example? The ajax handler could now look like this:

public function handleDelete($id)
{
	$this->connection->delete('ublaboo_example')
		->where('id = ?', $id)
		->execute();

	$this->flashMessage("Item deleted [$id] (actually, it was not)", 'info');

	if ($this->isAjax()) {
		$this->redrawControl('flashes');
		$this['actionsGrid']->reload();
	} else {
		$this->redirect('this');
	}
}

Redrawing one row

When you are updating row data (i.e. status), you can send only one row as snippet, not the whole table:

public function handleSetStatus($id, $status)
{
	$this->connection->update('ublaboo_example', ['status' => $satatus])
		->where('id = ?', $id)
		->execute();

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

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

Sortable

You can tell datagrid to be sortable (drag & drop):

$grid->setSortable();

This will show a handle in your datagrid. When you reorder items in datagrid, a nette.ajax request is sent as a signal to handler sort! in your presenter. Handler of datagrid above could look like this:

/**
 * @param  int      $item_id
 * @param  int|NULL $prev_id
 * @param  int|NULL $next_id
 * @return void
 */
public function handleSort($item_id, $prev_id, $next_id)
{
    $repository = $this->em->getRepository(Item::class);
    $item = $repository->find($item_id);

    /**
     * 1, Find out order of item BEFORE current item
     */
    if (!$prev_id) {
        $previousItem = NULL;
    } else {
        $previousItem = $repository->find($prev_id);
    }

    /**
     * 2, Find out order of item AFTER current item
     */
    if (!$next_id) {
        $nextItem = NULL;
    } else {
        $nextItem = $repository->find($next_id);
    }

    /**
     * 3, Find all items that have to be moved one position up
     */
    $itemsToMoveUp = $repository->createQueryBuilder('r')
        ->where('r.order <= :order')
        ->setParameter('order', $previousItem ? $previousItem->getOrder() : 0)
        ->andWhere('r.order > :order2')
        ->setParameter('order2', $item->getOrder())
        ->getQuery()
        ->getResult();

    foreach ($itemsToMoveUp as $t) {
        $t->setOrder($t->getOrder() - 1);
        $this->em->persist($t);
    }

    /**
     * 3, Find all items that have to be moved one position down
     */
    $itemsToMoveDown = $repository->createQueryBuilder('r')
        ->where('r.order >= :order')
        ->setParameter('order', $nextItem ? $nextItem->getOrder() : 0)
        ->andWhere('r.order < :order2')
        ->setParameter('order2', $item->getOrder())
        ->getQuery()
        ->getResult();

    foreach ($itemsToMoveDown as $t) {
        $t->setOrder($t->getOrder() + 1);
        $this->em->persist($t);
    }

    /**
     * Update current item order
     */
    if ($previousItem) {
        $item->setOrder($previousItem->getOrder() + 1);
    } else if ($nextItem) {
        $item->setOrder($nextItem->getOrder() - 1);
    } else {
        $item->setOrder(1);
    }

    $this->em->persist($item)->flush();

    $this->flashMessage("Id: $item_id, Previous id: $prev_id, Next id: $next_id", 'success');
    $this->redrawControl('flashes');

    $this['itemsGrid']->redrawControl();
}

Sorting hander

The name of the handler used for sorting can be changed:

$grid->setSortableHandler('foo!');

Also when you are using datagrid in component, you have to alter the name a bit:

$grid->setSortableHandler('myComponent:sort!');

MultiAction

Same as there is column status with pretty dropdown menu, ublaboo datagrid comes with similar dropdown menu for actions. It is called MultiAction:

/**
 * Multiaction
 */
$grid->addMultiAction('multi_action', 'MultiAction')
	->addAction('blah', 'Blahblah', 'blah!')
	->addAction('blah2', 'Blahblah2', 'blah!', ['name']);

Sure you can alter multiaction class, icons, etc. Same you can change icon, class, etc of nested actions:

$grid->getAction('multi_blah')
	->getAction('blah2')->setIcon('check');

Item detail

As you can see in the example on the homepage, there is a little eye button that toggles an item detail. This detail is loaded via ajax (just for the first time). The detail can be rendered in separate template or via custom renderer or in block #detail, which you define in you datagrid template. First, you need to enable the items detail functionality:

/**
 * This will enable rendering item detail in #detail block in your datagrid template
 */
$grid->setItemsDetail($detail = TRUE, $primary_where_column = $grid->primary_key); // Or just $grid->setItemsDetail();

/**
 * That would include separate detail template
 */
$grid->setItemsDetail(__DIR__ . '/templates/Datagrid/grid_item_detail.latte');

/**
 * And here is used just simple renderer callback
 */
$grid->setItemsDetail(function() { return 'Lorem Ipsum'; });

Item detail form

User may use a ItemDetail containing a form (ItemDetailForm). Example usage:

$presenter = $this;

$grid->setItemsDetail();

$grid->setItemsDetailForm(function(Nette\Forms\Container $container) use ($grid, $presenter) {
	$container->addHidden('id');
	$container->addText('name');

	$container->addSubmit('save', 'Save')
		->onClick[] = function($button) use ($grid, $presenter) {
			$values = $button->getParent()->getValues();

			$presenter['examplesGrid']->redrawItem($values->id);
		};
});

DataGrid user template:

{extends $original_template}

{block detail}
	<h2>{$item->name}</h2>

	<p>Lorem ipsum ...</p>

	{formContainer items_detail_form-$item->id}
		{input id, value => $item->id}
		{input name, value => $item->name}
		{input save}
	{/formContainer}
{/block}

Item detail template variables

Additional variables can be passed to item detail template (/block) via ItemDetail::setTemplateParameters(['foo' => 'bar', ...])

Item detail render condition

Custom callback can be set to decide whether to render item detail or not:

$grid->getItemsDetail()->setRenderCondition(function($item) {
	return TRUE;
});

ActionCallback

You don't have to fire event only using PresenterComponent signals. There is a possibility to fire events directly:

$grid->addActionCallback('custom_callback', '')
	->setIcon('sun-o')
	->setTitle('Hello, sun')
	->setClass('btn btn-xs btn-default ajax')
	->onClick[] = function($item_id) use ($presenter) {
		$presenter->flashMessage('Custom callback triggered, id: ' . $item_id);
		$presenter->redrawControl('flashes');
	};

You treat ActionCallback same as Action, except for some arguments passed to the DataGrid::addActionCallback method.

Toolbar button

If you need simple links to custom destinations from datagrid toolbar, they can be added like this:

$grid->addToolbarButton('this', 'Toolbar');
$grid->addToolbarButton('this', 'Button', ['foo' => 'bar']);

Additional attributes could be added to these buttons

$grid->addToolbarButton('this', 'Toolbar')
	->addAttributes(['foo' => 'bar']);
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