Working with data lists - Jet\DataListing

Jet DataList is a set of classes that makes it very easy to create lists of data. It provides the following functions:

  • Linking to ORM Jet DataModel
  • Pagination
  • Definition of columns and their behavior.
  • Vytváření libovolných filtrů.
  • The status of the list (filter settings and so on) is in the URL. It is therefore possible to easily send a filtered list of data between users.
  • Data exports
  • Bulk operations on filtered lists of data
  • Scroll through item details using the "previous" and "next" buttons.

Principle of operation

If you haven't done so already, please take a look at the administration of the sample application and try the event viewer. This is a good representative example of working with a list.

You can see that:

  • Above the grid with the list is a form with various filters
  • Of course, the filter form uses the forms system for definition, validation and rendering.
  • The filter form is sent as a POST, intercepted, validated and then a URL is built with GET parameters that finally define the actual filter settings.
  • The URL contains not only GET filter parameters, but also page numbers and sorting indication (by which column and in which direction the list should be sorted)
  • Thus, the URL fully defines the current list settings, and when another user opens it, they get the same list (unless the data has changed in the meantime, of course).
  • Under the filter is the data grid - i.e. the UI element for which the UI system and its UI_dataGrid element are used for rendering and basic operation.
  • It is automatically assumed that the data is manipulated using ORM DataModel and the paginator is also used.
  • Data can be exported.

It is clear that Jet\DataListing is in fact an integration tool that leverages other elements of the Jet platform to facilitate and unify the creation of such list interfaces. Thus, in the following we will focus on this integration feature. You'll learn more about working with forms, ORM DataModel, and UI_dataGrid in their respective chapters.

Create a list

The Jet\DataListing class is an abstract class and has a number of abstract methods that must be implemented.

Each specific list will be represented by its own class that defines it and that must therefore inherit from the Jet\DataListing class.

Let's show one particular class from the sample application, namely the list of events from the application module EventViewer.Admin:

namespace JetApplicationModule\EventViewer\Admin;

use 
Jet\DataListing;
use 
Jet\DataModel_Fetch_Instances;
use 
Jet\MVC_View;
use 
JetApplication\Logger_Admin_Event as Event;


class 
Listing extends DataListing {
    
    protected 
MVC_View $column_view;
    protected 
MVC_View $filter_view;
    
    public function 
__constructMVC_View $column_viewMVC_View $filter_view )
    {
        
$this->column_view $column_view;
        
$this->filter_view $filter_view;
        
        
$this->addColumn( new Listing_Column_ID() );
        
$this->addColumn( new Listing_Column_DateTime() );
        
$this->addColumn( new Listing_Column_EventClass() );
        
$this->addColumn( new Listing_Column_Event() );
        
$this->addColumn( new Listing_Column_EventMessage() );
        
$this->addColumn( new Listing_Column_ContextObjectId() );
        
$this->addColumn( new Listing_Column_ContextObjectName() );
        
$this->addColumn( new Listing_Column_UserId() );
        
$this->addColumn( new Listing_Column_UserName() );
        
        
$this->setDefaultSort'-id' );
        
        
$this->addFilter( new Listing_Filter_Search() );
        
$this->addFilter( new Listing_Filter_EventClass() );
        
$this->addFilter( new Listing_Filter_Event() );
        
$this->addFilter( new Listing_Filter_DateTime() );
        
$this->addFilter( new Listing_Filter_User() );
        
$this->addFilter( new Listing_Filter_ContextObject() );
        
        
$this->addExport( new Listing_Export_CSV() );
    }
    
    
    protected function 
getItemList(): DataModel_Fetch_Instances
    
{
        return 
Event::getList();
    }
    
    protected function 
getIdList(): array
    {
        
$ids Event::fetchIDs$this->getFilterWhere() );
        
$ids->getQuery()->setOrderBy$this->getQueryOrderBy() );
        
        return 
$ids->toArray();
    }
    
    public function 
itemGetterint|string $id ): mixed
    
{
        return 
Event::get$id );
    }
    
    public function 
getFilterView(): MVC_View
    
{
        return 
$this->filter_view;
    }
    
    public function 
getColumnView(): MVC_View
    
{
        return 
$this->column_view;
    }
    
    public function 
getItemURIint $item_id ) : string
    
{
        
$this->setParam('id'$item_id );
        
        
$URI $this->getURI();
        
        
$this->unsetParam('id');
        
        return 
$URI;
    }
    
}

... a tím je seznam definován.

Definition of columns

Each data column is represented by its own class, which must inherit from the abstract class Jet\DataListing_Column. Thus, the definition of each column is determined by a separate class, which has a wide range of options to influence the behavior of the column. And not only to influence its title, sorting options, but also how the column will be exported in bulk export. Of course, it is possible to hide columns or change their order. Just implement the necessary UI for this.

It is also true that each column has its own view script for displaying data.

See the chapter on columns for more information.

Definition of filters

The same applies to filters. Each filter is represented by its own class, which inherits from the abstract class Jet\DataListing_Filter. Each filter class manages the logic of a given filter, generates filter form fields, captures GET parameters, and builds the filter query for the ORM.

Here too I recommend to study the chapter on filters.

Definition of exports

And exports are no exception. Each export is represented by its own class, which inherits from the abstract class Jet\DataListing_Export.

However, the export has no predefined view. The UI implementation is up to you. However, creating exports is very easy. DataListing prepares the data and implementing the export is actually just about converting the data into the desired data format. There is already a pre-made Jet\DataListing_Export_CSV export.

There is also a chapter dedicated to exports, where you can find out more.

Definition of bulk operations

Bulk operations are operations that can be performed on a filtered list of data at once (e.g. delete all filtered items).

The principle is still the same. Each operation is represented by its own class, which inherits from the abstract class Jet\DataListing_Operation.

And of course there is a chapter dedicated to operations.

Using the list in the controller

We will follow our sample event viewer and show the corresponding methods of the controller of the module:

protected function getListing() : Listing
{
    if(!
$this->listing) {
        
$column_view = new MVC_View$this->view->getScriptsDir().'list/column/' );
        
$column_view->setController$this );
        
        
$filter_view = new MVC_View$this->view->getScriptsDir().'list/filter/' );
        
$filter_view->setController$this );
        
        
$this->listing = new Listing(
            
column_view$column_view,
            
filter_view$filter_view
        
);
    }
    
    return 
$this->listing;
}

public function 
listing_Action(): void
{
    
$listing $this->getListing();
    
$listing->handle();
        
    
$this->view->setVar'listing'$listing );

    
$this->output'list' );
}

The getListing method serves as a factory for creating a list instance. In this case, the view dependencies, i.e. the initialized view, must be injected into the list.

The list instance is a singleton in the controller because this instance can be used for more things than just browsing data, as we will see in a moment.

The listing_Action method is an example of a specific controller action whose purpose is to display the list of data. The action doesn't need to do anything other than get an instance of the list, call the $listing->handle(); method which will handle all the element logic and then pass the list instance to the view.

Use in view

Viewing the list, including its filters and operations, is easy, as you can see for yourself in the sample application, for example in the view script ~/application/Modules/EventViewer/Admin/views/listing.phtml.

It is important to get an instance of the filter form (if the list contains filters) and the UI element dataGrid in the view:

namespace JetApplicationModule\EventViewer\Admin;

use 
Jet\MVC_View;

/**
 * @var MVC_View  $this
 * @var Listing   $listing
 */
$listing $this->getRaw('listing');

$grid $listing->getGrid();
$filter_form $listing->getFilterForm();

Zobrazení filtrů se pak provádí takto:

<?=$filter_form->start()?>
    <div>
        <?=$listing->filter(Listing_Filter_Search::KEY)->renderForm()?>
    </div>
    <div>
        <?=$listing->filter(Listing_Filter_EventClass::KEY)->renderForm()?>
    </div>
    <div>
        <?=$listing->filter(Listing_Filter_Event::KEY)->renderForm()?>
    </div>
<?=$filter_form->end()?>

Recall that each filter has its own view script. This ensures clarity. By calling this, the corresponding view script is generated and the output is placed in the appropriate position.

Displaying the data grid itself is then very simple:

<div>
    <?=
$grid->render();?>
</div>

Again, each data column has its own view script. But of course it is possible to further influence the form and behavior of the columns. For example:

$grid->getColumnListing_Column_ID::KEY )->addCustomCssStyle'width:120px;' );

Use to browse items - next / previous

In the sample app, you may have noticed in the event viewer that you can browse events on the event detail using the "next" and "previous" buttons.

Here is the appropriate controller code that will take care of getting the URI of the previous or next list item relative to the currently open item:

if(($prev_item_id $listing->getPrevItemId$event->getId() ))) {
    
$this->view->setVar'prev_item_url'$listing->getItemURI$prev_item_id ) );
}

if((
$next_item_id $listing->getNextItemId$event->getId() ))) {
    
$this->view->setVar'next_item_url'$listing->getItemURI$next_item_id ) );
}

In the view, you only need to use these URIs:

$prev_item_url $this->getRaw('prev_item_url');
$next_item_url $this->getRaw('next_item_url');
?>
<div>
    <?=UI::button_goBack()->setUrl$this->getString'list_url' ))?>
        
    <?php if($prev_item_url): ?>
        <?=UI::button('')->setIcon('chevron-left')->setUrl($prev_item_url)->setClass(UI_button::CLASS_INFO)?>
    <?php endif; ?>
        
    <?php if($next_item_url): ?>
        <?=UI::button('')->setIcon('chevron-right')->setUrl($next_item_url)->setClass(UI_button::CLASS_INFO)?>
    <?php endif; ?>
</div>

Class Jet\DataListing

Abstract methods that need to be implemented

Method Meaning of
protected getItemList(
) : DataModel_Fetch_Instances
Returns a list of items via the ORM DataModel.

The method does not need to set up any filters or sorting. Everything is done by DataListing. Example: protected function getItemList(): DataModel_Fetch_Instances
{
    return 
User::fetchInstances();
}
protected getIdList(
) : array
Method for getting the ID of displayed items. It is mainly used for bulk operations. Unlike getItemList, getting the list of IDs is entirely a matter of method implementation. Example: protected function getIdList(): array
{
    
$ids User::fetchIDs$this->getFilterWhere() );
    
$ids->getQuery()->setOrderBy$this->getQueryOrderBy() );

    return 
$ids->toArray();
}
public getFilterView(
) : MVC_View
The list must already provide a fully initialized view instance for generating filters. In practice, this is most often handled by inserting dependencies using the constructor when creating the list instance.
public getColumnView(
) : MVC_View
The list must provide a fully initialized instance of view for generating data cells. In practice, this is most often handled by inserting dependencies using the constructor when creating the list instance.
public itemGetter(
int|string $id
) : mixed
For the purpose of exporting data, it is necessary to implement a method that returns a specific item based on the ID. Example: public function itemGetterint|string $id ): mixed
{
    return 
Event::get$id );
}

Working with columns

Method Meaning of
public getColumns(
) : DataListing_Column[]
Returns a list of all defined columns.
public addColumn(
DataListing_Column $column
) : void
Adds a column definition.
public columnExists(
string $column_key
) : bool
Indicates whether the column exists.
public column(
string $column_key
) : DataListing_Column
Returns a specific column.
public getVisibleColumns(
) : DataListing_Column[]
Returns a list of columns that are currently set to visible.
public getNotVisibleColumns(
) : DataListing_Column[]
Returns a list of columns that are currently set to invisible.

Working with exports

Method Meaning of
public getExports(
) : DataListing_Export[]
Returns a list of all defined exports.
public addExport(
DataListing_Export $export
) : void
Adds an export definition.
public exportExists(
string $key
) : bool
Indicates whether the export exists.
public export(
string $key
) : DataListing_Export
Returns the definition of the specific export.
public getExportTypes(
) : array
Returns a list of known exports in the form of an array where the key corresponds to the export key and the value of the export caption.
public getExportLimit(
) : int
Returns the limitation on the number of export items. If there is no limit, then -1 is returned.
public setExportLimit(
int $export_limit
) : void
Sets a limit on the number of export items.

Working with filters

Method Meaning of
public getFilters(
) : DataListing_Filter[]
Returns a list of all defined filters.
public addFilter(
DataListing_Filter $filter
) : void
Adds a filter definition.
public filterExists(
string $filter_key
) : bool
Indicates whether the filter exists.
public filter(
string $key
) : DataListing_Filter
Returns a specific filter.
protected catchFilterParams(
) : void
Internal method. Ensures capture of filter parameters.
public getFilterForm(
) : Form
Generates and returns a filter form.
protected catchFilterForm(
) : void
Internal method. Ensures the capture of the filter form.
public addFilterWhere(
array $where
) : void
The method by which individual filters set the generated WHERE for ORM.
protected getDefaultFilterWhere(
) : array
By overloading this method, it is possible to generate a default WHERE section for the ORM.
public getFilterWhere(
) : array
Returns the generated WHERE for ORM.

Working with bulk operations

Method Meaning of
public getOperations(
) : DataListing_Operation[]
Returns a list of defined operations.
public addOperation(
DataListing_Operation $operation
) : void
Adds an operation definition.
public operationExists(
string $operation
) : bool
Indicates whether the operation exists.
public operation(
string $operation
) : DataListing_Operation
Returns an instance of a specific operation.

Generator UI_dataGrid

Method Meaning of
public getGrid(
) : UI_dataGrid
Returns a fully initialized UI_dataGrid element.
protected createGridColumns(
) : void
Internal method. Converts column definitions to column definitions for UI_dataGrid.

Data paging

Method Meaning of
public createPaginator(
) : Data_Paginator
Creates, fully initializes, and returns a pager.
protected setPageNo(
int $page_no
) : void
The method of internal logic. Sets the current page number of the list.
protected setItemsPerPage(
int $items_per_page
) : void
The method of internal logic. Sets the number of items per list page.
protected catchPaginationParams(
) : void
The method of internal logic. Captures the current page number from the request.
protected getPageNo(
) : int
The method of internal logic. Returns the current page number.
protected getItemsPerPage(
) : int
The method of internal logic. Returns the current number of items on the list page.
protected getPaginatorURLCreator(
) : callable
The method of internal logic. Returns the URL creator for the page creator.

Methods for "previous" - "next" item function

Method Meaning of
public getPrevItemId(
int $item_id
) : string|int|null
Returns the ID of the previous item in the list based on the item ID (or null if the item is the first in the list).

Fully respects filtering and sorting - i.e. the current list settings.
public getNextItemId(
int $item_id
) : string|int|null
Returns the ID of the next item in the list based on the item ID (or null if there is no more item).

Fully respects filtering and sorting - i.e. the current list settings.

Data sorting

Method Meaning of
public setDefaultSort(
string $default_sort
) : void
Sets the default assignment for ORM.
public getDefaultSort(
) : string
Returns the default assignment for ORM.
public getQueryOrderBy(
) : string|array
Returns the current assignment for ORM reflecting the list settings.
protected setSort(
string $sort_by
) : void
The method of internal logic. Sets the sorting by column.
protected catchSortParams(
) : void
The method of internal logic. It captures the ordering parameter.
protected getGridSortBy(
) : string
The method of internal logic. Returns the sort settings for the UI element dataGrid.
protected getSortURLCreator(
) : callable
The method of internal logic. Generates a URL sort builder for the UI element dataGrid.

Parameters and URI generation

Method Význam
public setParam(
string $parameter,
mixed $value
) : void
Sets the value of the list parameter. An important method used especially by filters.
public unsetParam(
string $parameter
) : void
Cancels the list parameter. An important method used especially by filters.
public getURI(
) : string
Generates a list URI based on the current parameter settings.

General methods

Method Meaning of
public handle(
) : void
A method that provides processing of the internal logic of the list. Captures parameters, handles filter logic, sorting logic and paging. After calling this method, the list is already in the appropriate state and can be further manipulated (display, export data, or perform operations).
public getList(
) : DataModel_Fetch_Instances
Returns a fully configured data list using ORM.
public getAllIds(
) : array
Returns a list of all item IDs according to the current state of the list settings.
Previous chapter
Jet\Form_Definition_FieldOption
Next chapter
Columns - Jet\DataListing_Column