Rapid Application Development toolkit for building Administrative Web Applications

Radicore for PHP - Tutorial (Part 3)

By Tony Marston

26th October 2006

Introduction
Create transactions for the X_PERS_TYPE table
Create transactions for the X_TREE_TYPE table
Create transactions for the X_TREE_LEVEL table
   1. Modify Data Dictionary
   2. Generate LIST2 Transaction
   3. Add to navigation bar of parent
   4. Run the new Transaction
   5. Modify the screen structure file
   6. Modify screen labels, titles and button text
   7. Customise the ADD screen
   8. Create data for X_TREE_LEVEL
Create transactions for the X_TREE_NODE table
   1. Modify Data Dictionary
   2. Generate LIST2 Transaction
   3. Add to navigation bar of parent
   4. Run the new Transaction
   5. Modify the screen structure file
   6. Modify screen labels, titles and button text
   7. Customise the ADD screen
   8. Create data for X_TREE_NODE

Introduction

In Part 1 of this tutorial I described the initialisation procedure for a new application which is to be run under the Radicore framework, and the mechanism for generating new transactions.

In Part 2 I worked through a live example which created a basic forms family for maintaining the X_OPTION table in the test database.

In this part I shall deal with the basic tasks for dealing with the X_PERS_TYPE, X_TREE_TYPE, X_TREE_LEVEL and X_TREE_NODE tables.


Create transactions for the X_PERS_TYPE table

This is another transaction that we will access directly from a menu, not a navigation bar within another transaction, so we need to create a transaction of type LIST1.

The first step is to modify the data dictionary for this table using the values shown below:

Table Column Setting
x_pers_type pers_type_id UPPERCASE
created_date NOEDIT, AUTO-INSERT, NOSEARCH
created_user NOEDIT, AUTO-INSERT, NOSEARCH
revised_date NOEDIT, AUTO-UPDATE, NOSEARCH
revised_user NOEDIT, AUTO-UPDATE, NOSEARCH

For a description of what these settings mean please refer to Update Column.

After these changes have been made they must be made available to the application by running the Export to PHP function.

Now you can repeat step 2, step 3, step 4 and step 5 as shown in Part 2 of this tutorial.


Create transactions for the X_TREE_TYPE table

This is another transaction that we will access directly from a menu, not a navigation bar within another transaction, so we need to create a transaction of type LIST1.

The first step is to modify the data dictionary for this table using the values shown below:

Table Column Setting
x_tree_type tree_type_id UPPERCASE
created_date NOEDIT, AUTO-INSERT, NOSEARCH
created_user NOEDIT, AUTO-INSERT, NOSEARCH
revised_date NOEDIT, AUTO-UPDATE, NOSEARCH
revised_user NOEDIT, AUTO-UPDATE, NOSEARCH

For a description of what these settings mean please refer to Update Column.

After these changes have been made they must be made available to the application by running the Export to PHP function.

Now you can repeat step 2, step 3, step 4 and step 5 as shown in Part 2 of this tutorial.

After having created this family of transactions you can enter data such as the following:

Id Description
ORG Organisation
PROJ Project
TEST Test

Create transactions for the X_TREE_LEVEL table

1. Modify Data Dictionary

The first step is to modify the data dictionary for this table using the values shown below:

Table Column Setting
x_tree_level tree_type_id UPPERCASE
created_date NOEDIT, AUTO-INSERT, NOSEARCH
created_user NOEDIT, AUTO-INSERT, NOSEARCH
revised_date NOEDIT, AUTO-UPDATE, NOSEARCH
revised_user NOEDIT, AUTO-UPDATE, NOSEARCH

For a description of what these settings mean please refer to Update Column.

Using the Update Table screen also set 'Default Sort Seq' to tree_level_seq.

After these changes have been made they must be made available to the application by running the Export to PHP function.

2. Generate LIST2 Transaction

This is a transaction that we will not want to access directly from a menu because we want to select an entry from X_TREE_TYPE first, so we need to create a transaction of type LIST2 and add it to the navigation bar of the List X_TREE_TYPE transaction.

Using the Generate Transactions procedure select the X_TREE_LEVEL table, the LIST2 pattern, then press the SUBMIT button to bring up the screen shown in Figure 1:

Figure 1 - create LIST2 transaction for the X_TREE_LEVEL table

radicore-tutorial3-001 (10K)

For the 'Outer Table Name' field you must select the parent/senior table, which in this case is X_TREE_TYPE. When you press the SUBMIT button it will create the LIST2 transaction and all the child transactions listed in the 'Child forms' field.

Note that the list of tables for 'Outer Table Name' is taken from a single database identified as 'Outer database'. This defaults to the current database, but can be changed by pressing the popup button. This will cause the list of table names to be rebuilt from the contents of the selected database.

The following component scripts will be created in the subsystem directory as defined in the Create Subsystem screen:

  1. x_tree_level(list2).php
    <?php
    $outer_table = 'x_tree_type';                    // name of outer (parent) table
    $inner_table = 'x_tree_level';                   // name of inner (child) table
    $screen      = 'x_tree_level.list2.screen.inc';  // file identifying screen structure
    require 'std.list2.inc';                         // activate page controller
    ?>
    
  2. x_tree_level(add2).php
    <?php
    $table_id = 'x_tree_level';                      // table name
    $screen   = 'x_tree_level.detail.screen.inc';    // file identifying screen structure
    require 'std.add2.inc';                          // activate page controller
    ?>
    
  3. x_tree_level(del1).php
    <?php
    $table_id = 'x_tree_level';                      // table name
    $screen   = 'x_tree_level.detail.screen.inc';    // file identifying screen structure
    require 'std.del1.inc';                          // activate page controller
    ?>
    
  4. x_tree_level(enq1).php
    <?php
    $table_id = 'x_tree_level';                      // table name
    $screen   = 'x_tree_level.detail.screen.inc';    // file identifying screen structure
    require 'std.enq1.inc';                          // activate page controller
    ?>
    
  5. x_tree_level(search).php
    <?php
    $table_id = 'x_tree_level';                      // table name
    $screen   = 'x_tree_level.detail.screen.inc';    // file identifying screen structure
    require 'std.search1.inc';                       // activate page controller
    ?>
    
  6. x_tree_level(upd1).php
    <?php
    $table_id = 'x_tree_level';                      // table name
    $screen   = 'x_tree_level.detail.screen.inc';    // file identifying screen structure
    require 'std.upd1.inc';                          // activate page controller
    ?>
    

The following screen structure scripts will be created in the <subsystem>/screens/<language> directory where <language> is the default language code as selected in the Update Control Data screen.

  1. x_tree_level.list2.screen.inc
    <?php
    $structure['xsl_file'] = 'std.list2.xsl';
    
    $structure['tables']['outer'] = 'x_tree_type';
    
    // identify the column specs - may use 'width' or 'class'
    $structure['outer']['columns'][] = array('width' => '25%');
    $structure['outer']['columns'][] = array('width' => '*');
    
    // identify the field names and their screen labels
    $structure['outer']['fields'][] = array('tree_type_id' => 'Tree Type Id');
    $structure['outer']['fields'][] = array('tree_type_desc' => 'Tree Type Desc');
    $structure['outer']['fields'][] = array('created_date' => 'Created Date');
    $structure['outer']['fields'][] = array('created_user' => 'Created User');
    $structure['outer']['fields'][] = array('revised_date' => 'Revised Date');
    $structure['outer']['fields'][] = array('revised_user' => 'Revised User');
    
    $structure['tables']['inner'] = 'x_tree_level';
    
    // identify the column specs - may use 'width' or 'class'
    $structure['inner']['columns'][] = array('width' => 5);
    $structure['inner']['columns'][] = array('width' => '12.5%');
    $structure['inner']['columns'][] = array('width' => '12.5%');
    $structure['inner']['columns'][] = array('width' => '12.5%');
    $structure['inner']['columns'][] = array('width' => '12.5%');
    $structure['inner']['columns'][] = array('width' => '12.5%');
    $structure['inner']['columns'][] = array('width' => '12.5%');
    $structure['inner']['columns'][] = array('width' => '12.5%');
    $structure['inner']['columns'][] = array('width' => '12.5%');
    
    // identify the field names and their screen labels
    $structure['inner']['fields'][] = array('selectbox' => 'Select');
    $structure['inner']['fields'][] = array('tree_type_id' => 'Tree Type Id');
    $structure['inner']['fields'][] = array('tree_level_id' => 'Tree Level Id');
    $structure['inner']['fields'][] = array('tree_level_seq' => 'Tree Level Seq');
    $structure['inner']['fields'][] = array('tree_level_desc' => 'Tree Level Desc');
    $structure['inner']['fields'][] = array('created_date' => 'Created Date');
    $structure['inner']['fields'][] = array('created_user' => 'Created User');
    $structure['inner']['fields'][] = array('revised_date' => 'Revised Date');
    $structure['inner']['fields'][] = array('revised_user' => 'Revised User');
    ?>
    
  2. x_tree_level.detail.screen.inc
    <?php
    $structure['xsl_file'] = 'std.detail1.xsl';
    
    $structure['tables']['main'] = 'x_tree_level';
    
    // identify the column specs - may use 'width' or 'class'
    $structure['main']['columns'][] = array('width' => '25%');
    $structure['main']['columns'][] = array('width' => '*');
    
    // identify the contents of each row in the table 
    $structure['main']['fields'][] = array('tree_type_id' => 'Tree Type Id');
    $structure['main']['fields'][] = array('tree_level_id' => 'Tree Level Id');
    $structure['main']['fields'][] = array('tree_level_seq' => 'Tree Level Seq');
    $structure['main']['fields'][] = array('tree_level_desc' => 'Tree Level Desc');
    $structure['main']['fields'][] = array('created_date' => 'Created Date');
    $structure['main']['fields'][] = array('created_user' => 'Created User');
    $structure['main']['fields'][] = array('revised_date' => 'Revised Date');
    $structure['main']['fields'][] = array('revised_user' => 'Revised User');
    ?>
    

3. Add to navigation bar of parent

This part is not done automatically, so it has to be done manually. Navigate to home->menu system->task (proc) and locate the parent task which in this case is tst_x_tree_type(list1). Then press the 'Navigation Button(1)' button which should bring up the screen shown in Figure 2;

Figure 2 - navigation buttons for parent task

radicore-tutorial3-002 (14K)

Press the 'New' button which should bring up the Choose Task popup screen. Select task tst_x_tree_level(list2) and press the CHOOSE button, which should return you to the previous screen with the new entry added at the bottom, as shown in Figure 3:

Figure 3 - amended navigation buttons for parent task

radicore-tutorial3-003 (15K)

4. Run the new Transaction

In order to run this transaction you must navigate to home->test->x_tree_type, which should bring up the screen shown in Figure 4:

Figure 4 - list X_TREE_TYPE screen

radicore-tutorial3-004 (7K)

Note here that I have already added several entries. Select one of them and press the 'x_tree_level' button in the navigation bar. This should bring up the screen shown in Figure 5:

Figure 5 - list X_TREE_LEVEL within X_TREE_TYPE screen (original)

radicore-tutorial3-005 (9K)

5. Modify the screen structure file

By default the generated screen structure file, called x_tree_level.list2.screen.inc, contains all available fields for the specified tables. If you modify it as shown below you will see the result shown in Figure 6:

<?php
$structure['xsl_file'] = 'std.list2.xsl';

$structure['tables']['outer'] = 'x_tree_type';

// identify the column specs - may use 'width' or 'class'
$structure['outer']['columns'][] = array('width' => '25%');
$structure['outer']['columns'][] = array('width' => 80);
$structure['outer']['columns'][] = array('width' => 100);
$structure['outer']['columns'][] = array('width' => '*');

// identify the field names and their screen labels
$structure['outer']['fields'][1][] = array('label' => 'Tree Type Id');
$structure['outer']['fields'][1][] = array('field' => 'tree_type_id');
$structure['outer']['fields'][1][] = array('label' => 'Description');
$structure['outer']['fields'][1][] = array('field' => 'tree_type_desc');

$structure['tables']['inner'] = 'x_tree_level';

// identify the column specs - may use 'width' or 'class'
$structure['inner']['columns'][] = array('width' => 5);
$structure['inner']['columns'][] = array('width' => 50);
$structure['inner']['columns'][] = array('width' => 50);
$structure['inner']['columns'][] = array('width' => '*');

// identify the field names and their screen labels
$structure['inner']['fields'][] = array('selectbox' => 'Select');
$structure['inner']['fields'][] = array('tree_level_id' => 'Id');
$structure['inner']['fields'][] = array('tree_level_seq' => 'Seq');
$structure['inner']['fields'][] = array('tree_level_desc' => 'Description');
?>

Figure 6 - list X_TREE_LEVEL within X_TREE_TYPE screen (modified)

radicore-tutorial3-006 (7K)

6. Modify screen labels, titles and button text

Follow the procedure described in Part 2 of this tutorial to replace the default text with customised values.

7. Customise the ADD screen

If you run the generated ADD screen it will initially look like Figure 7:

Figure 7 - the default ADD screen

radicore-tutorial3-007 (5K)

There are two things wrong with this screen:

  1. Instead of displaying the foreign key TREE_TYPE_ID I would like to display a descriptive field from the foreign table.
  2. I would like both TREE_LEVEL_ID and TREE_LEVEL_SEQ to be automatically generated, not manually input.

Point (1) above is very easy - simply edit file x_tree_level.detail.screen.inc and replace the line which reads:

$structure['main']['fields'][] = array('tree_type_id' => 'Tree Type Id');

with a line which reads:

$structure['main']['fields'][] = array('tree_type_desc' => 'Tree Type');

This will produce the result shown in Figure 8:

Figure 8 - the modified ADD screen (1)

radicore-tutorial3-008 (5K)

How is it possible for this transaction to automatically retrieve a field from a parent table without me having to write any SQL? This is due to the relationship information which was put into the data dictionary, as shown in Figure 9:

Figure 9 - relationship between X_TREE_TYPE and X_TREE_LEVEL

radicore-tutorial3-009 (10K)

When this information is exported to the file x_tree_level.dict.inc it appears as follows:

$this->parent_relations[] = array('parent' => 'x_tree_type',
                                  'parent_field' => 'tree_type_desc',
                                  'fields' => array('tree_type_id' => 'tree_type_id'));

This provides some useful information:

This information is used by the getForeignData() method to retrieve the value contained within tree_type_desc from the x_tree_type table using the current value for tree_type_id. This value is added to the object's $fieldarray which in turn is transferred to the XML file so that it can be built into the screen during the XSL transformation process.

It is also used when reading from the database to modify the sql SELECT statement which is constructed. The default statement:

SELECT * 
FROM x_tree_level 
WHERE x_tree_level.tree_type_id='ORG' AND x_tree_level.tree_level_id='1'

is changed to:

SELECT x_tree_level.*, x_tree_type.tree_type_desc 
FROM x_tree_level 
LEFT JOIN x_tree_type ON (x_tree_type.tree_type_id=x_tree_level.tree_type_id) 
WHERE x_tree_level.tree_type_id='ORG' AND x_tree_level.tree_level_id='1'

Point (2) above will require some code to be added to file x_tree_level.class.inc. Start by copying across the empty _cm_getInitialData() method from the abstract table class which is std.table.class.inc, then fill it with the code shown below:

    function _cm_getInitialData ($fieldarray)
    // Perform custom processing for the getInitialData method.
    // $fieldarray contains data from the initial $where clause.
    {
        if (!empty($fieldarray['tree_type_id'])) {
            // get next available number for tree_level_id
            $where = "tree_type_id='{$fieldarray['tree_type_id']}'";
            $query = "SELECT max(tree_level_id) FROM $this->tablename WHERE $where";
            $count = $this->getCount($query);
            $fieldarray['tree_level_id']  = $count + 1;
            $fieldarray['tree_level_seq'] = $count + 1;
        } // if

        // set these fields to 'noedit' (read only)
        $this->fieldspec['tree_level_id']['noedit']  = 'y';
        $this->fieldspec['tree_level_seq']['noedit'] = 'y';

        return $fieldarray;

    } // _cm_getInitialData

The result of this change is shown in Figure 10:

Figure 10 - the modified ADD screen (2)

radicore-tutorial3-010 (5K)

Another change we want to make is to force the TREE_LEVEL_SEQ field to be non-editable all all screens except the search screen, which can be done by copying across the empty _cm_changeConfig() method from file std.table.class.inc, then filling it with the code shown below:

    function _cm_changeConfig ($where, $fieldarray)
    // Change the table configuration for the duration of this instance.
    // $where = a string in SQL 'where' format.
    // $fieldarray = the contents of $where as an array.
    {
        switch ($GLOBALS['mode']) {
            case 'search':
                unset($this->fieldspec['tree_level_seq']['noedit']);
                break;
            
            default:
                $this->fieldspec['tree_level_seq']['noedit'] = 'y';
                break;
        } // switch

        return $fieldarray;

    } // _cm_changeConfig

8. Create data for X_TREE_LEVEL

After having created this family of transactions you can enter data for type 'Organisation' such as the following:

Id Seq Description
1 1 Company
2 2 Department
3 3 Section

Create transactions for the X_TREE_NODE table

1. Modify Data Dictionary for X_TREE_NODE table

Table Column Setting
x_tree_node tree_type_id UPPERCASE
node_id_snr NOEDIT
created_date NOEDIT, AUTO-INSERT, NOSEARCH
created_user NOEDIT, AUTO-INSERT, NOSEARCH
revised_date NOEDIT, AUTO-UPDATE, NOSEARCH
revised_user NOEDIT, AUTO-UPDATE, NOSEARCH

For a description of what these settings mean please refer to Update Column.

After these changes have been made they must be made available to the application by running the Export to PHP function.

2. Generate LIST2 Transaction

This is a transaction that we will not want to access directly from a menu because we want to select an entry from X_TREE_LEVEL first, so we need to create a transaction of type LIST2 and add it to the navigation bar of the List X_TREE_LEVEL transaction.

Using the Generate Transactions procedure select the X_TREE_NODE table, the LIST2 pattern, then press the SUBMIT button to bring up the screen shown in Figure 11:

Figure 11 - create LIST2 transaction for the X_TREE_NODE table

radicore-tutorial3-011 (10K)

For the 'Outer Table Name' field you must select the parent/senior table, which in this case is X_TREE_LEVEL. When you press the SUBMIT button it will create the LIST2 transaction and all the child transactions listed in the 'Child forms' field.

The following component scripts will be created in the subsystem directory as defined in the Create Subsystem screen:

  1. x_tree_node(list2).php
    <?php
    $outer_table = 'x_tree_level';                  // name of outer (parent) table
    $inner_table = 'x_tree_node';                   // name of inner (child) table
    $screen      = 'x_tree_node.list2.screen.inc';  // file identifying screen structure
    require 'std.list2.inc';                        // activate page controller
    ?>
    
  2. x_tree_node(add2).php
    <?php
    $table_id = 'x_tree_node';                      // table name
    $screen   = 'x_tree_node.detail.screen.inc';    // file identifying screen structure
    require 'std.add2.inc';                         // activate page controller
    ?>
    
  3. x_tree_node(del1).php
    <?php
    $table_id = 'x_tree_node';                      // table name
    $screen   = 'x_tree_node.detail.screen.inc';    // file identifying screen structure
    require 'std.del1.inc';                         // activate page controller
    ?>
    
  4. x_tree_node(enq1).php
    <?php
    $table_id = 'x_tree_node';                      // table name
    $screen   = 'x_tree_node.detail.screen.inc';    // file identifying screen structure
    require 'std.enq1.inc';                         // activate page controller
    ?>
    
  5. x_tree_node(search).php
    <?php
    $table_id = 'x_tree_node';                      // table name
    $screen   = 'x_tree_node.detail.screen.inc';    // file identifying screen structure
    require 'std.search1.inc';                      // activate page controller
    ?>
    
  6. x_tree_node(upd1).php
    <?php
    $table_id = 'x_tree_node';                      // table name
    $screen   = 'x_tree_node.detail.screen.inc';    // file identifying screen structure
    require 'std.upd1.inc';                         // activate page controller
    ?>
    

The following screen structure scripts will be created in the <subsystem>/screens/<language> directory where <language> is the default language code as selected in the Update Control Data screen.

  1. x_tree_node.list2.screen.inc
    <?php
    $structure['xsl_file'] = 'std.list2.xsl';
    
    $structure['tables']['outer'] = 'x_tree_level';
    
    // identify the column specs - may use 'width' or 'class'
    $structure['outer']['columns'][] = array('width' => '25%');
    $structure['outer']['columns'][] = array('width' => '*');
    
    // identify the field names and their screen labels
    $structure['outer']['fields'][] = array('tree_type_id' => 'Tree Type Id');
    $structure['outer']['fields'][] = array('tree_level_id' => 'Tree Level Id');
    $structure['outer']['fields'][] = array('tree_level_seq' => 'Tree Level Seq');
    $structure['outer']['fields'][] = array('tree_level_desc' => 'Tree Level Desc');
    $structure['outer']['fields'][] = array('created_date' => 'Created Date');
    $structure['outer']['fields'][] = array('created_user' => 'Created User');
    $structure['outer']['fields'][] = array('revised_date' => 'Revised Date');
    $structure['outer']['fields'][] = array('revised_user' => 'Revised User');
    
    $structure['tables']['inner'] = 'x_tree_node';
    
    // identify the column specs - may use 'width' or 'class'
    $structure['inner']['columns'][] = array('width' => 5);
    $structure['inner']['columns'][] = array('width' => '10%');
    $structure['inner']['columns'][] = array('width' => '10%');
    $structure['inner']['columns'][] = array('width' => '10%');
    $structure['inner']['columns'][] = array('width' => '10%');
    $structure['inner']['columns'][] = array('width' => '10%');
    $structure['inner']['columns'][] = array('width' => '10%');
    $structure['inner']['columns'][] = array('width' => '10%');
    $structure['inner']['columns'][] = array('width' => '10%');
    $structure['inner']['columns'][] = array('width' => '10%');
    $structure['inner']['columns'][] = array('width' => '10%');
    
    // identify the field names and their screen labels
    $structure['inner']['fields'][] = array('selectbox' => 'Select');
    $structure['inner']['fields'][] = array('node_id' => 'Node Id');
    $structure['inner']['fields'][] = array('tree_type_id' => 'Tree Type Id');
    $structure['inner']['fields'][] = array('tree_level_id' => 'Tree Level Id');
    $structure['inner']['fields'][] = array('node_desc' => 'Node Desc');
    $structure['inner']['fields'][] = array('node_id_snr' => 'Node Id Snr');
    $structure['inner']['fields'][] = array('external_code' => 'External Code');
    $structure['inner']['fields'][] = array('created_date' => 'Created Date');
    $structure['inner']['fields'][] = array('created_user' => 'Created User');
    $structure['inner']['fields'][] = array('revised_date' => 'Revised Date');
    $structure['inner']['fields'][] = array('revised_user' => 'Revised User');
    ?>
    
  2. x_tree_node.detail.screen.inc
    <?php
    $structure['xsl_file'] = 'std.detail1.xsl';
    
    $structure['tables']['main'] = 'x_tree_node';
    
    // identify the column specs - may use 'width' or 'class'
    $structure['main']['columns'][] = array('width' => '25%');
    $structure['main']['columns'][] = array('width' => '*');
    
    // identify the contents of each row in the table 
    $structure['main']['fields'][] = array('node_id' => 'Node Id');
    $structure['main']['fields'][] = array('tree_type_id' => 'Tree Type Id');
    $structure['main']['fields'][] = array('tree_level_id' => 'Tree Level Id');
    $structure['main']['fields'][] = array('node_desc' => 'Node Desc');
    $structure['main']['fields'][] = array('node_id_snr' => 'Node Id Snr');
    $structure['main']['fields'][] = array('external_code' => 'External Code');
    $structure['main']['fields'][] = array('created_date' => 'Created Date');
    $structure['main']['fields'][] = array('created_user' => 'Created User');
    $structure['main']['fields'][] = array('revised_date' => 'Revised Date');
    $structure['main']['fields'][] = array('revised_user' => 'Revised User');
    ?>
    

3. Add to navigation bar of parent

This part is not done automatically, so it has to be done manually. Navigate to home->menu system->task (proc) and locate the parent task which in this case is tst_x_tree_level(list2). Then press the 'Navigation Button(1)' button which should bring up the screen shown in Figure 12;

Figure 12 - navigation buttons for parent task

radicore-tutorial3-012 (14K)

Press the 'New' button which should bring up the Choose Task popup screen. Select task tst_x_tree_node(list2) and press the CHOOSE button, which should return you to the previous screen with the new entry added at the bottom, as shown in Figure 13:

Figure 13 - amended navigation buttons for parent task

radicore-tutorial3-013 (15K)

4. Run the new Transaction

In order to run this transaction you must navigate to home->test->x_tree_type, select 'Organisation' and then press the 'x_tree_level' button in the navigation bar. This should bring up the screen shown in Figure 14:

Figure 14 - list X_TREE_LEVEL screen

radicore-tutorial3-014 (8K)

Note here that I have already added several entries. Select one of them and press the 'x_tree_node' button in the navigation bar. This should bring up the screen shown in Figure 15:

Figure 15 - list X_TREE_NODE within X_TREE_SCREEN screen (original)

radicore-tutorial3-015 (9K)

5. Modify the screen structure file

By default the generated screen structure file, called x_tree_node.list2.screen.inc, contains all available fields for the specified tables. If you modify it as shown below you will see the result shown in Figure 16:

<?php
$structure['xsl_file'] = 'std.list2.xsl';

$structure['tables']['outer'] = 'x_tree_level';

// identify the column specs - may use 'width' or 'class'
$structure['outer']['columns'][] = array('width' => '25%');
$structure['outer']['columns'][] = array('width' => 10);
$structure['outer']['columns'][] = array('width' => '*');

// identify the field names and their screen labels
$structure['outer']['fields'][] = array('tree_type_desc' => 'Tree Type', 'colspan' => 2);
$structure['outer']['fields'][1][] = array('label' => 'Tree Level');
$structure['outer']['fields'][1][] = array('field' => 'tree_level_seq');
$structure['outer']['fields'][1][] = array('field' => 'tree_level_desc');

$structure['tables']['inner'] = 'x_tree_node';

// identify the column specs - may use 'width' or 'class'
$structure['inner']['columns'][] = array('width' => 5);
$structure['inner']['columns'][] = array('width' => 50);
$structure['inner']['columns'][] = array('width' => '*');
$structure['inner']['columns'][] = array('width' => 50);
$structure['inner']['columns'][] = array('width' => 120);

// identify the field names and their screen labels
$structure['inner']['fields'][] = array('selectbox' => 'Select');
$structure['inner']['fields'][] = array('node_id' => 'Id');
$structure['inner']['fields'][] = array('node_desc' => 'Description');
$structure['inner']['fields'][] = array('node_id_snr' => 'Parent');
$structure['inner']['fields'][] = array('external_code' => 'External Code');
?>

Figure 16 - list X_TREE_NODE within X_TREE_LEVEL screen (modified)

radicore-tutorial3-016 (7K)

6. Modify screen labels, titles and button text

Follow the procedure described in Part 2 of this tutorial to replace the default text with customised values.

7. Customise the ADD screen

If you run the generated ADD screen it will initially look like Figure 17:

Figure 17 - the default ADD screen

radicore-tutorial3-017 (6K)

There are three things wrong with this screen:

  1. Instead of displaying the foreign keys TREE_TYPE_ID and TREE_LEVEL_ID I would like to display descriptive fields from the foreign tables.
  2. I would like TREE_NODE_ID to be generated automatically, not manually input.
  3. NODE_ID_SNR is to be invisible on the add screen.

Point (1) above is very easy - simply edit file x_tree_node.detail.screen.inc and replace the lines which read:

$structure['main']['fields'][] = array('node_id' => 'Node Id');
$structure['main']['fields'][] = array('tree_type_id' => 'Tree Type Id');
$structure['main']['fields'][] = array('tree_level_id' => 'Tree Level Id');

with lines which read:

$structure['main']['fields'][] = array('tree_type_desc' => 'Tree Type');
$structure['main']['fields'][] = array('tree_level_desc' => 'Tree Level');
$structure['main']['fields'][] = array('node_id' => 'Node Id');

This makes use of the functionality which has been explained previously.

Points (2) and (3) above will require some code to be added to file x_tree_node.class.inc. Start by copying across the empty _cm_getInitialData() method from the abstract table class which is std.table.class.inc, then fill it with the code shown below:

    function _cm_getInitialData ($fieldarray)
    // Perform custom processing for the getInitialData method.
    // $fieldarray contains data from the initial $where clause.
    {
        // set node_id to next available number
        $count = $this->getCount("SELECT max(node_id) FROM $this->tablename");
        $fieldarray['node_id'] = $count + 1;

        $this->fieldspec['node_id']['noedit'] = 'y';

        $fieldarray['node_id_snr'] = null;
        $this->fieldspec['node_id_snr']['nodisplay'] = 'y';

        return $fieldarray;

    } // _cm_getInitialData

The combined effects of these changes will produce the result shown in Figure 18:

Figure 18 - the modified ADD screen (1)

radicore-tutorial3-018 (6K)

8. Create data for X_TREE_NODE

After having created this family of transactions you can enter data such as the following:

Type Level Description External Code
Organisation Company AJM Enterprises Ltd AJME
AJM Solutions Ltd AMJS
Organisation Department Department #1 -1
Department #2 -2
Department #3 -3
Department #4 -4
Department #5 -5
Department #6 -6
Organisation Section Section #1 -1
Section #2 -2
Section #3 -3
Section #4 -4
Section #5 -5
Section #6 -6
Section #7 -7
Section #8 -8
Section #9 -9
Section #10 -10

You should notice two important points at this stage:

  1. When a node is created it is fixed to a particular level within a particular type (i.e. neither TREE_TYPE_ID or TREE_LEVEL_ID can be changed). This is quite deliberate. If you create a node at the 'Company' level it would be quite illogical to move it to the 'Department' level.
  2. A hierarchy of nodes is produced by linking a child node with its parent - the parent's NODE_ID is placed in the NODE_ID_SNR field of the child node. This means that a node can either have one parent (or no parent at all), but it can have any number of children.
  3. A node can only have a parent which exists at the level which is immediately above it (i.e. a node at level 3 can only have a parent from level 2). This also means the following:

These rules require that the attaching and detaching of a parent node with its children be handled by specialised tasks, which I shall describe in Part 4.


© Tony Marston
26th October 2006

http://www.tonymarston.net
http://www.radicore.org

counter