Componette

Componette

uestla

uestla / TwiGrid 12.0.7

TwiGrid - datagrid built on top of Nette Framework

download-cloud-line composer require uestla/twigrid

TwiGrid

... is a DataGrid for Nette Framework.

Buy me a Coffee

Demo: https://kesspess.cz/twigrid/
Demo sources: https://github.com/uestla/twigrid-demo

It's based on another (and great) datagrid written by @hrach - https://github.com/nextras/datagrid. My datagrid is hugely inspired by this component and its programming ideas and therefore I would like to give this man a maximum credit and respect :-)

Quickstart

Let's see how many steps do we have to make to create our first datagrid.

  1. Create new project

    composer create-project nette/web-project twigrid-quickstart
  2. Install TwiGrid & client-side assets

    cd twigrid-quickstart
    composer require uestla/twigrid
    yarn add twigrid-datagrid --modules-folder www/assets/vendor

    If you're not using yarn, you can install assets manually by looking into package.json and see required dependencies there.

    We'll then update app/Presentation/@layout.latte to load downloaded assets - just replace {asset? 'main.js'} with:

    <!-- app/Presentation/@layout.latte -->
    
    {asset 'vendor/bootstrap/dist/css/bootstrap.min.css'}
    {asset 'vendor/twigrid-datagrid/assets/twigrid.datagrid.css'}
    
    {asset 'vendor/jquery/dist/jquery.min.js'}
    {asset 'vendor/bootstrap/dist/js/bootstrap.min.js'}
    {asset 'vendor/nette-forms/src/assets/netteForms.min.js'}
    {asset 'vendor/nette.ajax.js/nette.ajax.js'}
    {asset 'vendor/twigrid-datagrid/assets/twigrid.datagrid.js'}
    
    {asset 'script.js'}

    Then we'll create www/assets/script.js with Nette Forms and nette.ajax initialization:

    Nette.initOnLoad();
    
    $(function () {
    	$.nette.init();
    });
  3. Database

    Download the SQLite3 file from the demo application and place it in app/Model/users.s3db.

    And we'll configure this database to be used by the application:

    # config/common.neon
    database:
    	dsn: 'sqlite:%appDir%/Model/users.s3db'
  4. Create datagrid

    Now it's finally time to create our first datagrid - let's create an app/Grids/UsersGrid.php file. We'll need database connection for data loading, so we inject it properly via constructor.

    // app/Grids/UsersGrid.php
    
    /** @implements TwiGrid\DataGrid<Nette\Database\Table\ActiveRow> */
    final class UsersGrid extends TwiGrid\DataGrid
    {
    	public function __construct(
    		private readonly Nette\Database\Explorer $database,
    	) {
    		parent::__construct();
    	}
    
    	protected function build(): void
    	{
    		// TODO
    	}
    }

    We'll define the datagrid body inside the build() method. Although the table user has many columns, we'll have just some of them in our grid just to make it easy.

    // app/Grids/UsersGrid.php
    
    /** @implements TwiGrid\DataGrid<Nette\Database\Table\ActiveRow> */
    final class UsersGrid extends TwiGrid\DataGrid
    {
    	// ...
    
    	protected function build(): void
    	{
    		$this->addColumn('firstname', 'Firstname');
    		$this->addColumn('surname', 'Surname');
    		$this->addColumn('streetaddress', 'Street address');
    		$this->addColumn('city', 'City');
    		$this->addColumn('country_code', 'Country');
    	}
    }

    TwiGrid also needs to know what column(s) it should consider as a primary key:

    $this->setPrimaryKey('id');

    And finally we'll tell TwiGrid how to load our users:

    $this->setDataLoader(fn() => $this->database->table('user'));
  5. Factory

    To properly inject our grid into presenters, we'll need to create a factory interface:

    // app/Grids/UsersGridFactory.php
    
    interface UsersGridFactory
    {
    	public function create(): UsersGrid;
    }

    This interface will now be used for automatic factory generation and autowired thanks to SearchExtension, which is handy.

  6. Presenter

    Having all of this done, we can now simply inject our grid factory into HomePresenter.

    // app/Presentation/Home/HomePresenter.php
    
    final class HomePresenter extends Nette\Application\UI\Presenter
    {
    	public function __construct(
    		private readonly \UsersGridFactory $usersGridFactory,
    	) {
    		parent::__construct();
    	}
    }

    Now we'll add the control factory itself:

    // app/Presentation/Home/HomePresenter.php
    
    protected function createComponentUsersGrid(): \UsersGrid
    {
    	return $this->usersGridFactory->create();
    }
  7. Render the grid

    We're nearly done! Just open app/Presentation/Home/default.latte and replace the whole content with

    {block content}
    	<div class="container">
    		<h1>UsersGrid example</h1>
    
    		{control usersGrid}
    	</div>
    {/block}
  8. Custom template

    Maybe showing the country code isn't that sexy - we'd like to have the whole country name in "Country" column. To achieve that, we'll create custom grid template:

    {* app/Grids/UsersGrid.latte *}
    
    {extends $defaultTemplate}
    
    {define body-cell-country_code}
    	<td>{$record->country->title}</td>
    {/define}

    And tell TwiGrid to use this template:

    // app/Grids/UsersGrid.php::build()
    
    $this->setTemplateFile(__DIR__ . '/UsersGrid.latte');

    That's all, folks!

    Now when you'll open the page, you might see something like this:

    Result screenshot

More

To see more examples, please visit the demo page. Enjoy!

  • 12.0.7 12.0.7

    Various fixes for new nette/* package versions + support for PHP 8.4

  • 12.0.6 12.0.6

  • 12.0.2

    • Migrated bower to yarn
    • Upgraded CI pipeline
    • Updated & improved README
  • 12.0.0

  • 11.2.1 TwiGrid 11.2.1

    This is the last release for PHP 5.6.x

    I want to rewrite the core of this library to PHP7 static & return typehints and then release it as a new major version 12.

    I will only deal with bugfixes/security patches for this 11.x version, but no new features are to be added.

Componette Componette felix@nette.org