Core Concepts

Agile Toolkit and Agile UI are built upon specific core concepts. Understanding those concepts is very important especially if you plan to write and distribute your own add-ons.


In any Agile UI application you will always need to have an App class. Even if you do not create this class explicitly, components generally will do it for you. The common pattern is:

$app = new \Atk4\Ui\App('My App');


Agile UI is developed to be easy to read and with simple and concise syntax. We make use of PHP’s dynamic nature, therefore two syntax patterns are supported everywhere:

Button::addTo($app, ['Hello']);


Button::addTo($app, ['Hello']);

Method add() supports arguments in various formats and we call that “Seed”. The same format can be used elsewhere, for example:

$button->icon = 'book';

We call this format ‘Seed’. This section will explain how and where it is used.

Render Tree

Agile Toolkit allows you to create components hierarchically. Once complete, the component hierarchy will render itself and will present HTML output that would appear to user.

You can create and link multiple UI objects together before linking them with other chunks of your UI:

$msg = new \Atk4\Ui\Message('Hey There');
Button::addTo($msg, ['Button']);


To find out more about how components are linked up together and rendered, see:

Sticky GET

Agile UI implements advanced approach allowing any View object that you add into render tree to declare “sticky GET arguments”. Here is example:

if ($app->hasRequestQueryParam('message')) {

Button::addTo($app, ['Trigger message'])->link(['message' => 'Hello World']);

The code is simple - if you click the button, page will appear with the message just above, however there is a potential problem here. What if “Message” wanted to perform a Callbacks? What if we use Console instead, which must display an interactive data stream?

In Agile UI you can request that some $_GET arguments are preserved and included into callback urls:

if ($this->getApp()->stickyGet('message')) {

Button::addTo($app, ['Trigger message'])->link(['message' => 'Hello World']);

There are two types of “sticky” parameters, application-wide and view-specific.

Type Presentation

Several components are too complex to be implemented in a single class. Table, for example, has the ability to format columns by utilizing type-specific column classes. Another example is Form which relies on Field-specific Form\Control component.

Agile UI uses a specific pattern for those definitions, which makes the overall structure more extensible by having the ability to introduce new types with consistent support throughout the UI.


Agile UI components store their HTML inside *.html template files. Those files are loaded and manipulated by a Template class.

To learn more on how to create a custom template or how to change global template behavior see:

Agile Data

Agile UI framework is focused on building User Interfaces, but quite often interface must present data values to the user or even receive data values from user’s input.

Agile UI uses various techniques to present data formats, so that as a developer you wouldn’t have to worry over the details:

$user = new User($db);
$user = $user->load(1);

$view = View::addTo($app, ['template' => 'Hello, {$name}, your balance is {$balance}']);

Next section will explain you how the Agile UI interacts with the data layer and how it outputs or inputs user data.


By relying on the ability of generating Unique Name, it’s possible to create several classes for implementing PHP callbacks. They follow the pattern:

  • present something on the page (maybe)

  • generate URL with unique parameter

  • if unique parameter is passed back, behave differently

Once the concept is established, it can even be used on a higher level, for example:

$button->on('click', function () {
    return 'clicked button';


Building on the foundation of Callbacks, components VirtualPage and Loader exist to enhance other Components with dynamically loadable content. Here is example for Tabs:

$tabs = Tabs::addTo($app);
LoremIpsum::addTo($tabs->addTab('First tab is static'));

$tabs->addTab('Second tab is dynamic', function (VirtualPage $vp) {

As you switch between those two tabs, you’ll notice that the Button label on the “Second tab” reloads every time. Tabs implements this by using VirtualPage, read further to find out how:

Documentation is coming soon.