Code Corner 2 Using Etemplate - Nilpferdschaf/Egroupware-Doku GitHub Wiki

<< Prev.: Getting Started

Using eTemplate

eTemplate is the custom templating language used by EGroupware. It is based on XML, but luckily you do not need to worry about that most of the time. EGroupware comes included with a graphical editor for eTemplates. Some features are missing from it, so you will have to dive into the code sometimes, but thanks to the XML structure, editing is relatively straightforward.

The eTemplate Editor

To access the eTemplate editor you will have to go to your Admin tab and give yourself access rights to it, just like you did with the Hello World application during the previous tutorial. You should see the eTemplate tab on the left after a page refresh. Click on it.

Accessing the eTemplate Editor A first look at the editor

What we are going to create now is a small form to input a name, position and department. This could be shown to every new user of your EGroupware installation so they can input their information and automatically be assigned to their appropriate user groups. It will also display a personalized Hello World message. This is what it should look like after you are done.

The full UI

To start editing a new template, open the eTemplate editor and enter "helloworld.index" into the name field. By naming it this way, you tell EGW that you want to create a template called index for the app "helloworld". You will see this naming convention a lot in the future. For now, it is important for you to remember to begin all template names with "$appname.".
Enter some version number and press Save. Just ignore the Template and Lang fields for now.

Now hover with your mouse in the upper left corner of the big white area below the menu bar. A small pink rectangle should appear beneath the mouse pointer. If you can not find it, try pressing Ctrl-A to make it more visible. Once you have found it, double click to open the widget editor.

Accessing the eTemplate Editor Accessing the eTemplate Editor

There is quite a lot going on here. The first thing we will look at in detail is the dropdown menu labeled Type. This determines what kind of UI element we want to create. Have a look through the list. The default type is Label, but you can have all common UI elements and even some pre-configured selectors for dates, times, priorities, and many more.
You will also notice some structural widgets like grids, h- and vboxes, tables or tabs. These are different from normal widgets in that they can contain other widgets and lay them out in a predefined way.
If you take a look at the Path, you will see that you are currently working within a grid structure. This is the default that is loaded every time you create a new template: Just a label within a 1x1 grid. To set the content of the label, type "Position:" into the Label field and click Apply. You should see your changes appear in the background.

Settings for position label

Have a look at the top row of selection boxes now. Here you have options to edit the grid, like cut-copy-pasting widgets or inserting/deleting rows and columns. Use these to insert a new row below the current one. The widget editor will close and you will be taken back to the template view. If you hover your mouse below the label you just edited, a new pink rectangle will have appeared.

The newly appeared pink rectangle

Double click it to reopen the widget editor. Select Label as the Type and insert "Department:" as the content. Click Apply and watch you changes appear in the background. Use the selection boxes at the top to insert a second column into the grid, after the column we are in now.

There are two new pink rectangles now, one after each label. Double click the top one. This time the Type should be Text. Click Apply and a text box will appear in the template view in the background. Now enter "Enter position" into the field after blurText and hit Apply again. The string will appear inside the text box. We will also give this text box an identifier by which we can address it from our code. That is what the Name field is for. Insert the string "position" here and then hit Apply one more time.

Settings for position text box.

Take a look at Path again. You might notice the arrows that have appeared here. You can use these to navigate within the grid. Play around with these to make yourself familiar with the navigation. You can also go up a level by clicking on grid. This allows you to change settings for the grid itself. To get back, click on the little x that has now appeared in the path. It is meant to resemble an arrow pointing away from you and into the screen, meaning "Go inside". Using the arrows, navigate to the one widget we have not touched yet, the one after Department: and underneath Enter position. Its Type will be Select Box and its Name "dep_id". Click Apply again.

Settings for the department selector

Now navigate to the grid widget by using the grid link after Path again. At the top, instead of the options for inserting rows and columns into the grid, you now have options to insert widgets before and after the grid itself. Use these options to insert a widget before the grid. Set its Type to HBox and put a "4" into the Options field. This last step ensures the hbox will have space for exactly four widgets, which will be aligned horizontally in a row. Click Apply to make the changes visible. Then navigate into the hbox (press the x after Path) and insert two labels and two text fields, such that the form looks like the picture below. Set the Name options of the first and second text field to "fname" and "sname", respectively.

Creating a new widget before the grid Settings for the hbox. The form with the name fields

For the submit button, navigate back to the grid widget again. Create a new widget after the grid, set its Type to Submit Button and set both the Label and Name to "submit". Finally, click Save.

Creating a new widget after the grid Settings for the submit button.

Try clicking Export XML now. If helloworld.index.xet starts downloading, that means the EGW server does not have writing rights to the templates folder of your app. To fix this, execute

command line:
chown -R www-data $egw_installation/helloworld/templates

in a terminal, then try Export XML again. Every time you edit a template, you should click Save and then Export XML. Save only writes your changes into a buffer, while Export XML actually writes the changes into a file.
If you take a look at $egw_installation/helloworld/templates/default/, you should now find a new file there called index.xet. This has been written by the editor.

Updating the code

With the template complete, you need to integrate it with your code somehow. You will now start writing actual PHP code. Before you begin, you should take a look at Egrouwares coding standards. This will help you write code that looks and feels the same as the EGW source code. There is also a developer guide and a style guide.

As previously mentioned, most of the code should be inside the helloworld/inc/ folder. Create a new file class.helloworld_ui.inc.php inside this folder. This is another naming convention. All ui object classnames should end in "_ui", all business objects in "_bo" and all storage objects in "_so". Files containing a class should be named "class.$classname.inc.php". Insert the following code into this file:

class.helloworld_ui.inc.php:
<?php
use EGroupware\Api\Etemplate;

class helloworld_ui {

    function index($content = null)
    {
        $content = array();

        $departments = array(
            'Human Resources',
            'Marketing',
            'Tech Support',
            'Sales',
            'Management'
        );

        $selection_options = array(
            'dep_id' => $departments
        );

        $tmpl = new Etemplate ('helloworld.index');
        $tmpl->exec ('helloworld.helloworld_ui.index', $content, $selection_options);
    }
}

Note that the function is named index() after the template you just created. It does not have to be the same name, but again, it is convention to do it like this. Let us take a closer look at the last two lines. First of all, we create a new etemplate-object called $tmpl. The constructor takes one argument, which is the name of our template file.

In the final line, the exec() function is called. This function automatically generates the entire page, without any additional work required. It takes three arguments, the first is a callback string in the format "$app.$class.$function". This method is called whenever the user submits data back to the server, as will be the case once you click on the submit button. The second argument is the $content array. It contains all the information needed to populate the template with content. There is nothing to populate at this point, so it will be empty. The last argument is an array used to populate things like selection boxes, content lists, or content trees. We use it to set some options for the department selection box.

You should also note the import on the first line, EGroupware\Api\Etemplate. It is required to use the classes that belong to eTemplate.

If you go to EGroupware and open the app, you will see... Hello World!. That's because we still need to edit helloworld/index.php to point to the newly created function. Delete everything that is in there at the moment and replace it with

index.php:
<?php
header('Location: ../index.php?menuaction=helloworld.helloworld_ui.index');

This is basically the same you did when setting the callback method for the exec() function. It tells EGroupware to create an instance of helloworld_ui and call its index() function.

Finally, add the following variable definition to class.helloworld_ui.inc.php:

class.helloworld_ui.inc.php:
public $public_functions = array(
    'index' => true
);

EGroupware only allows calling functions through the menuaction parameter which are registered in this array. Otherwise, it would be easy to call any function by passing the corresponding string to the menuaction.

Reopen the app in EGroupware. You will see the form you created. It does not do anything though. Clicking on Submit just resets everything. This is no surprise, because there is nothing interesting happening inside the index() function. This will change now. Quickly go back to the eTemplate editor and add a Text Area underneath the Submit button. Name it debug and tick the readonly option. Now it will only be possible to edit the content of the text area through code. It will also be invisible unless it has content, so do not wonder if you can not see it yet.

Settings for the debug text area.

You will now use this text area to output some debug information. When index.php calls index for the first time, it will do so without any parameters. $content will therefore be set to null, by default. When you click Submit, index is called once again, this time as the callback method, and as such, it will be passed an array as parameter containing the entire content of the template. To see how it works, update the index() function like this:

class.helloworld_ui.inc.php:
function index($content = null) 
{
    $departments = array(
        'Human Resources',
        'Marketing',
        'Tech Support',
        'Sales',
        'Management'
    );

    if (is_array ($content))
    {
        $content ['debug'] =
            "Hello " . $content ['fname'] . " " . $content ['sname'] .
            ". You are working as " . $content['position'] .
            " in " . $departments[$content['dep_id']] . ".\n";
    }
    else
    {
        $content = array();
    }

    $selection_options = array(
        'dep_id' => $departments
    );

    $tmpl = new Etemplate ('helloworld.index');
    $tmpl->exec ('helloworld.helloworld_ui.index', $content, $selection_options);
}

The code is now checking wether $content is an array and if it is not, initializes it with an empty array. More interestingly, if $content is an array, the data from the form is parsed into a string and output to the debug area. Try it out now.

Trying out the form.

Defining the $departments array inside the index() function is bad style. This definition should be moved to the constructor. The constructor will be called automatically by EGW. In fact, a new instance of helloworld_ui is created every time you reload the page: When index is called via the menuaction parameter. Inside the constructor you can also do some other fancy things, like setting the page title of your app. The updated file looks like this:

class.helloworld_ui.inc.php:
<?php
use EGroupware\Api\Etemplate;

class helloworld_ui
{
    public $public_functions = array(
            'index' => true
    );
    private $departments;

    function __construct()
    {
        $this->departments = array(
                'Human Resources',
                'Marketing',
                'Tech Support',
                'Sales',
                'Management'
        );

        $GLOBALS ['egw_info'] ['flags'] ['app_header'] = 'Enter your position.';
    }

    function index($content = null)
    {
        if (is_array ($content))
        {
            $content ['debug'] =
                "Hello " . $content ['fname'] . " " . $content ['sname'] .
                ". You are working as " . $content ['position'] .
                " in " . $this->departments [$content ['dep_id']] . ".\n";
        }
        else
        {
            $content = array();
        }

        $selection_options = array(
                'dep_id' => $this->departments
        );

        $tmpl = new Etemplate ('helloworld.index');
        $tmpl->exec ('helloworld.helloworld_ui.index', $content, $selection_options);
    }
}

and the final thing running in EGroupware looks like this:

The full UI

Conclusion

As you have probably guessed by now, eTemplate is quite powerful, but also extensive and complicated. This was only a quick look at some of the more basic features. There is still lots to be learned in the later sections, but for now we will have a look at EGroupware's database tools.

Download

You can download the result of this section here.

Next: Database Tools >>

^ Back to top

⚠️ **GitHub.com Fallback** ⚠️