Tabella
Komponenta pro vizualizaci tabulek nad databázovou vrstvou Dibi. Klíčovými vlastnostmi je konfigurovatelnost a možnost na každý pohled, stránku, či filtr jednoznačně odkazovat, neb všechny požadavky (mimo inline editaci) se provádí pouze metodou GET.
| Download | https://github.com/knyttl/Tabella |
| Demo | http://tabella.knyt.tl/ |
| Forum | http://forum.nette.org/…rid-pro-dibi |
| Autor | Vojtech Knyttl, http://knyt.tl (vojtech@) |
| Licence | New BSD License |
Komponenta je stále ve vývoji, proto prosím omluvte nedostatky:
- editace a filtry dle checkboxu
- absence textarey
- filtr dle data funguje jen v některých případech (problémy s pluginem datePicker)
- překlad jak hlavičky, tak vybraných sloupců – např.
$grid = new Tabella( array( "translator" => $this->translator ) );
...
$grid->addColumn( "…", "…", array( "translate" => true ) );
Budu vděčný za jakoukoliv kritiku.

Příklad základního použití
Pro všechny následující případe předpokládejme následující DB model:
CREATE TABLE users_test (
id int(11) NOT NULL AUTO_INCREMENT,
surname varchar(128),
name varchar(128),
sex enum('male','female') NOT NULL,
born int(11),
dead int(11),
daughters int(11),
sons int(11),
PRIMARY KEY (id)
);
<?php
class UsersModel extends Object {
public static function dataSource() {
return dibi::dataSource( "SELECT *, (daughters + sons) as children FROM users_test" );
}
public static function save( $set, $id = 0) {
if( $id == 0 )
dibi::query( "INSERT INTO users_test", $set );
else
dibi::query( "UPDATE users_test SET ", $set, "WHERE id = %i", $id );
}
public static function delete( $id ) {
dibi::query( "DELETE FROM users_test WHERE id = %i", $id );
}
}
?>
Komponentu potom vytvoříme továrničkou na komponenty následovně:
<?php
protected function createComponentBasicTabella( $name ) {
$grid = new Tabella( UsersModel::getDataSource() );
$grid->addColumn( "Id", "id", array( "width" => 30 ) );
$grid->addColumn( "Surame", "surname", array( "width" => 100 ) );
$grid->addColumn( "Name", "name", array( "width" => 100 ) );
$grid->addColumn( 'Sex', 'sex', array( "width" => 50 ) );
$grid->addColumn( "Sons", "sons", array( "width" => 65 ) );
$grid->addColumn( "Daughters", "daughters", array( "width" => 65 ) );
$grid->addColumn( 'Born', 'born', array( "type" => Tabella::DATETIME ) );
$grid->addColumn( 'Dead', 'dead', array( "type" => Tabella::DATETIME ) );
$this->addComponent( $grid, $name );
}
?>
Klíčový je v podstatě pouze příkaz addColumn pro přidání sloupce. První parametr udává zobrazované jméno, druhým je název sloupce v DB a třetí je pole parametrů. V základním zobrazení si prozatím vystačím se šířkou (udanou v pixelech) a typem. Typ může nabývat hodnot: TEXT, TEXTAREA, SELECT, CHECKBOX, DATETIME, DATE, TIME. Položky TEXTAREA, SELECT, CHECKBOX se ale týkají pouze inline editace (viz dále).
Funčkní ukázka je dostupná na http://tabella.zatorsky.cz/basic.
Příklad komplexního použití
Opět použijeme továrničku na komponenty:
<?php
protected function createComponentComplexTabella( $name ) {
$grid = new Tabella( UsersModel::dataSource(), array(
"order" => "surname", // default order by surname
"limit" => 15, // limit
"rowRenderer" => function( $row ) {
return Html::el( "tr class=".$row->sex );
}
));
?>
V komplexním příkladu nejprve ukazujeme, jak je v inicializaci možné docílit defaultního řazení, omezení počtu řádků na stránce a vlastní generování řádků, které podle pohlaví přiřazuje barvu. Možností je samozřejmě mnohem více.
<?php
$grid->addColumn( 'Id', 'id', array(
"width" => 30
));
$grid->addColumn( "Surame", "surname", array(
"renderer" => function( $row ) {
// can be a link within the application
return Html::el( "td class=al" )->add( Html::el( 'a target=_blank' )
->href( Environment::getApplication()->getPresenter()
->link( "this", array( "id" => $row->id ) ) )
->add( String::truncate( $row->surname, 25 ) ) );
return $td;
},
// own filter handler which reacts on change in the filter input
"filterHandler" => function( $val ) {
return "surname LIKE '$val%'";
},
"width" => 100
));
?>
Generování příjmení je zajímavé v tom, že jsme použili vlastní renderer buňky, který pro daného uživatele generuje nějaký odkaz.
<?php
$grid->addColumn( "Name", "name", array(
// own filter handler which reacts on change in the filter input
"filterHandler" => function( $val ) {
return "name LIKE '$val%'";
},
"class" => array( "center", "upper" ),
// html class can be a string or array
"width" => 100
));
$grid->addColumn( 'Sex', 'sex', array(
"width" => 50,
// makes selectbox filter
"filter" => array( "" => "", "male" => "male", "female" => "female" ),
"filterHandler" => function( $val ) {
return "sex = '$val'";
}
));
?>
Zde je zajímavý pouze filtr přes selectbox. Stačí přiřadit do položky filter array s výčtem a Tabella se o zbytek postará.
<?php
$grid->addColumn( "Children", "children", array(
"width" => 40,
"filter" => array(
"" => "",
0 => "having none",
1 => "having son",
2 => "having daughter",
3 => "having both" ),
"filterHandler" => function( $col, $val ) {
switch( $val ) {
case 0: return "children = 0";
case 1: return "sons > 0";
case 2: return "daughters > 0";
case 3: return "sons > 0 AND daughters > 0";
}
},
"headerElement" => Html::el( "th colspan=2" ),
"renderer" => function( $row ) {
$td = Html::el( "td width=17" )->add( $row->sons ).
Html::el( "td width=17" )->add( $row->daughters );
return $td;
}
));
?>
Zde máme příklad, jak je možné vytvořit hlavičku s colspan=2. Data jsou řazená dle součtu dcer a synů, k čemuž jsou ještě definovány komplexnější filtry.
<?php
$grid->addColumn( 'Born', 'born', array(
"type" => Tabella::DATE,
"class" => "center",
"dateFormat" => "%Y/%m/%d",
"filterHandler" => function( $val ) {
$start = strtotime( "$val 00:00" );
$end = $start + 86400;
return "born > $start AND born < $end";
}
));
$grid->addColumn( 'Dead', 'dead', array(
"type" => Tabella::DATE,
"class" => "center",
"dateFormat" => "%Y/%m/%d",
"filterHandler" => function( $val ) {
$start = strtotime( "$val 00:00" );
$end = $start + 86400;
return "born > $start AND born < $end";
}
));
$this->addComponent( $grid, $name );
?>
}
Na konec pouze naznačme, jak je možné formátovat vlastním způsobem datum.
Funčkní ukázka je dostupná na http://tabella.zatosky.cz/complex.
Inline-editovatelná Tabella
Klíčovou vlastností Tabelly je inline editace:
<?php
protected function createComponentEditableTabella( $name ) {
$grid = new Tabella( UsersModel::dataSource(), array(
"limit" => 15, // limit
"sorting" => "desc",
"onSubmit" => function( $post ) {
$post['born'] = strtotime( $post['born'] );
UsersModel::save( $post, $post['id'] );
},
"onDelete" => function( $id ) {
UsersModel::delete( $id );
}
));
?>
Pro inline editaci je nezbytné zadat handler onSubmit, který bude zavolán pro uložení odeslaných dat. V našem případě data předáváme pouze modelu.
<?php
$grid->addColumn( "Id", "id", array( "width" => 30 ) );
$grid->addColumn( "Surname", "surname", array(
"width" => 100,
"editable" => true
));
$grid->addColumn( "Name", "name", array(
"width" => 100,
"editable" => true ));
$grid->addColumn( 'Sex', 'sex', array(
"type" => Tabella::SELECT,
"options" => array( 'male' => 'Male', 'female' => 'Female' ),
"width" => 50,
"editable" => true,
));
?>
Pro výčet v selectboxu použijeme volbu „options“.
<?php
$grid->addColumn( "Sons", "sons", array(
"width" => 65,
"editable" => true
));
$grid->addColumn( "Daughters", "daughters", array(
"width" => 65,
"editable" => true
));
$grid->addColumn( "Born", "born", array(
"type" => Tabella::DATE,
"dateFormat" => "%Y/%m/%d",
"editable" => true
));
$grid->addColumn( "+", Tabella::ADD, array(
"type" => Tabella::DELETE
));
$this->addComponent( $grid, $name );
?>
Pokud položku názvu v databázi nahradíme za konstantu Tabella:ADD, vznikne v hlavičce sloupce přidávací tlačítko. Pokud typ nastavíme na Tabella::DELETE, ve sloupci přibude tlačítko na smazání – volá se handler onDelete.
Ukázka editovatelné Tabelly je na http://tabella.zatorsky.cz/editable.
Komentáře 
gerades | 4. 12. 2010, 19:22 | comment
Kdyz se rekne komponenta, tak by mela byt jednoduse pouzitelna a dobre zdokumentovana. Tenhle navod a zdrojaky na stahnuti jsou k nicemu.
gerades | 4. 12. 2010, 20:12 | comment
Taky by bylo fajn, dopsat pro jakou verzi PHP, Nette to je.
vlna | 10. 5. 2011, 12:11 | comment
Famozni, diky ;-)
MartyIX | 1. 7. 2011, 10:38 | bug
Jack06 | 1. 10. 2011, 11:53 | question
Zajímalo by mě, zda se dají nějakým způsobem cachovat data, která tabella bere. Je to pěkné ta práce s dataSource, ale hodilo by se cachovat. Při rozsáhlejších datech je to rapidně znát. Nicméně dataSource pokud vím se cachovat nedá. Nějaký nápad?

maarlin | 26. 9. 2010, 10:33 | comment
Ukázka na http://tabella.goout.cz/editable hlásí 404.