{"id":14965541,"url":"https://github.com/uestla/twigrid","last_synced_at":"2025-10-25T11:32:01.585Z","repository":{"id":6171557,"uuid":"7401423","full_name":"uestla/TwiGrid","owner":"uestla","description":"TwiGrid - datagrid built on top of Nette Framework","archived":false,"fork":false,"pushed_at":"2023-09-17T17:24:14.000Z","size":510,"stargazers_count":17,"open_issues_count":6,"forks_count":10,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-01-31T07:05:20.558Z","etag":null,"topics":["datagrid","filtering","group-actions","inline-editing","nette","pagination","php","row-actions","sorting","twitter-bootstrap"],"latest_commit_sha":null,"homepage":"http://forum.nette.org/cs/13181-twigrid-omlouvam-se","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/uestla.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-01-02T02:27:59.000Z","updated_at":"2023-10-24T12:21:12.000Z","dependencies_parsed_at":"2024-09-13T23:39:46.175Z","dependency_job_id":"df5bab71-73ef-47c6-9378-a48a23ad3b9c","html_url":"https://github.com/uestla/TwiGrid","commit_stats":{"total_commits":365,"total_committers":3,"mean_commits":"121.66666666666667","dds":"0.010958904109588996","last_synced_commit":"fd77c0c8dd974270c5655f0766ac366a9314fac1"},"previous_names":[],"tags_count":66,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uestla%2FTwiGrid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uestla%2FTwiGrid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uestla%2FTwiGrid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uestla%2FTwiGrid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uestla","download_url":"https://codeload.github.com/uestla/TwiGrid/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238128653,"owners_count":19421076,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["datagrid","filtering","group-actions","inline-editing","nette","pagination","php","row-actions","sorting","twitter-bootstrap"],"created_at":"2024-09-24T13:34:53.404Z","updated_at":"2025-10-25T11:32:01.580Z","avatar_url":"https://github.com/uestla.png","language":"PHP","funding_links":["https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=5UZMKSVARNKJL"],"categories":[],"sub_categories":[],"readme":"# TwiGrid\n\n... is a DataGrid for Nette Framework.\n\n[![Buy me a Coffee](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=5UZMKSVARNKJL)\n\n**Demo**: https://kesspess.cz/twigrid/  \n**Demo sources**: https://github.com/uestla/twigrid-demo\n\nIt'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 :-)\n\n\n# Quickstart\n\nLet's see how many steps do we have to make to create our first datagrid.\n\n1. ### Create new project\n\n\t```shell\n\tcomposer create-project nette/web-project twigrid-quickstart\n\t```\n\n2. ### Install TwiGrid \u0026 client-side assets\n\n\t```shell\n\tcd twigrid-quickstart\n\tcomposer require uestla/twigrid\n\tyarn add twigrid-datagrid --modules-folder www/assets/vendor\n\t```\n\n\t\u003e If you're not using yarn, you can install assets manually by looking into `package.json` and see required dependencies there.\n\n\tWe'll then update `app/Presentation/@layout.latte` to load downloaded assets - just replace `{asset? 'main.js'}` with:\n\n\t```latte\n\t\u003c!-- app/Presentation/@layout.latte --\u003e\n\n\t{asset 'vendor/bootstrap/dist/css/bootstrap.min.css'}\n\t{asset 'vendor/twigrid-datagrid/assets/twigrid.datagrid.css'}\n\n\t{asset 'vendor/jquery/dist/jquery.min.js'}\n\t{asset 'vendor/bootstrap/dist/js/bootstrap.min.js'}\n\t{asset 'vendor/nette-forms/src/assets/netteForms.min.js'}\n\t{asset 'vendor/nette.ajax.js/nette.ajax.js'}\n\t{asset 'vendor/twigrid-datagrid/assets/twigrid.datagrid.js'}\n\n\t{asset 'script.js'}\n\t```\n\n\tThen we'll create `www/assets/script.js` with Nette Forms and nette.ajax initialization:\n\n\t```javascript\n\tNette.initOnLoad();\n\n\t$(function () {\n\t\t$.nette.init();\n\t});\n\t```\n\n3. ### Database\n\n\tDownload [the SQLite3 file](https://github.com/uestla/twigrid-demo/raw/455d55d2e2a34bae9aaa64658bf8a4b6ddfca4a0/app/users.s3db) from the demo application and place it in `app/Model/users.s3db`.\n\n\tAnd we'll configure this database to be used by the application:\n\n\t```neon\n\t# config/common.neon\n\tdatabase:\n\t\tdsn: 'sqlite:%appDir%/Model/users.s3db'\n\t```\n\n4. ### Create datagrid\n\n\tNow 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.\n\n\t```php\n\t// app/Grids/UsersGrid.php\n\n\t/** @implements TwiGrid\\DataGrid\u003cNette\\Database\\Table\\ActiveRow\u003e */\n\tfinal class UsersGrid extends TwiGrid\\DataGrid\n\t{\n\t\tpublic function __construct(\n\t\t\tprivate readonly Nette\\Database\\Explorer $database,\n\t\t) {\n\t\t\tparent::__construct();\n\t\t}\n\n\t\tprotected function build(): void\n\t\t{\n\t\t\t// TODO\n\t\t}\n\t}\n\t```\n\n\tWe'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.\n\n\t```php\n\t// app/Grids/UsersGrid.php\n\n\t/** @implements TwiGrid\\DataGrid\u003cNette\\Database\\Table\\ActiveRow\u003e */\n\tfinal class UsersGrid extends TwiGrid\\DataGrid\n\t{\n\t\t// ...\n\n\t\tprotected function build(): void\n\t\t{\n\t\t\t$this-\u003eaddColumn('firstname', 'Firstname');\n\t\t\t$this-\u003eaddColumn('surname', 'Surname');\n\t\t\t$this-\u003eaddColumn('streetaddress', 'Street address');\n\t\t\t$this-\u003eaddColumn('city', 'City');\n\t\t\t$this-\u003eaddColumn('country_code', 'Country');\n\t\t}\n\t}\n\t```\n\n\tTwiGrid also needs to know what column(s) it should consider as a primary key:\n\n\t```php\n\t$this-\u003esetPrimaryKey('id');\n\t```\n\n\tAnd finally we'll tell TwiGrid how to load our users:\n\n\t```php\n\t$this-\u003esetDataLoader(fn() =\u003e $this-\u003edatabase-\u003etable('user'));\n\t```\n\n5. ### Factory\n\n\tTo properly inject our grid into presenters, we'll need to create a factory interface:\n\n\t```php\n\t// app/Grids/UsersGridFactory.php\n\n\tinterface UsersGridFactory\n\t{\n\t\tpublic function create(): UsersGrid;\n\t}\n\t```\n\n\tThis interface will now be used for automatic factory generation and autowired thanks to [SearchExtension](https://doc.nette.org/en/dependency-injection/configuration#toc-search), which is handy.\n\n6. ### Presenter\n\n\tHaving all of this done, we can now simply inject our grid factory into `HomePresenter`.\n\n\t```php\n\t// app/Presentation/Home/HomePresenter.php\n\n\tfinal class HomePresenter extends Nette\\Application\\UI\\Presenter\n\t{\n\t\tpublic function __construct(\n\t\t\tprivate readonly \\UsersGridFactory $usersGridFactory,\n\t\t) {\n\t\t\tparent::__construct();\n\t\t}\n\t}\n\t```\n\n\tNow we'll add the control factory itself:\n\n\t```php\n\t// app/Presentation/Home/HomePresenter.php\n\n\tprotected function createComponentUsersGrid(): \\UsersGrid\n\t{\n\t\treturn $this-\u003eusersGridFactory-\u003ecreate();\n\t}\n\t```\n\n7. ### Render the grid\n\n\tWe're nearly done! Just open `app/Presentation/Home/default.latte` and replace the whole content with\n\n\t```latte\n\t{block content}\n\t\t\u003cdiv class=\"container\"\u003e\n\t\t\t\u003ch1\u003eUsersGrid example\u003c/h1\u003e\n\n\t\t\t{control usersGrid}\n\t\t\u003c/div\u003e\n\t{/block}\n\t```\n\n8. ### Custom template\n\n\tMaybe 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:\n\n\t```latte\n\t{* app/Grids/UsersGrid.latte *}\n\n\t{extends $defaultTemplate}\n\n\t{define body-cell-country_code}\n\t\t\u003ctd\u003e{$record-\u003ecountry-\u003etitle}\u003c/td\u003e\n\t{/define}\n\t```\n\n\tAnd tell TwiGrid to use this template:\n\n\t```php\n\t// app/Grids/UsersGrid.php::build()\n\n\t$this-\u003esetTemplateFile(__DIR__ . '/UsersGrid.latte');\n\t```\n\n\tThat's all, folks!\n\n\tNow when you'll open the page, you might see something like this:\n\n\t![Result screenshot](https://i.imgur.com/7y8D0ow.png)\n\nMore\n----\n\nTo see more examples, please visit the [demo page](https://kesspess.cz/twigrid/). Enjoy!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuestla%2Ftwigrid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuestla%2Ftwigrid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuestla%2Ftwigrid/lists"}