Having worked my way painfully through this, I thought I would post a quick example / tutorial as it how this may be done.
MIGXdb.
Create Custom Manager Page(s) for two linked tables (one to many)
Requirements
1. Install MigX (if not already done)
2. Create a new Package and schema-file
3. The Schema
4. Parse Schema
5. Create Table(s)
6. Create the Configuration
7. Add a Menu Item
8. Add records to the tables
This Example was built using ModX 2.5.0 pl and MigX 2.9.6
1. Install MigX (if not already done)
First of all, install MIGX using standard package-management, and do the basic configuration.
Go to Components->MIGX->Tab 'Set-up/Upgrade', and under the 'Setup' tab click 'Setup'.
2. Create a new Package and schema-file
Go to Components->MIGX->Tab 'Package Manager'.
Add a name for the new package using the field 'packageName:'. For this example use 'yourpackagename'.
Click 'Create Package' This should create a directory under the core-path with an empty schema-file in its correct place.
Still having 'yourpackagename' in the field 'packageName', now fill the textarea-field 'Schema' under the tab 'Xml Schema' using the data below.
3. The Schema
<?xml version="1.0" encoding="UTF-8"?>
<model package="yourpackagename" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" version="1.1">
<!--
I suggest that you use a package name derived prefix for your tables to help to separate your tables
from ModX tables or tables created by other packages - I have used 'ypn'
-->
<object class="table1Class" table="ypn_table1" extends="xPDOSimpleObject">
<field key="table1_key" dbtype="varchar" precision="3" phptype="string" null="false" default=""/>
<field key="table1_field1" dbtype="text" phptype="string" null="false" default=""/>
<!-- Used by MigX -->
<field key="deleted" dbtype="tinyint" precision="1" attributes="unsigned" phptype="integer" null="false" default="0" />
<field key="published" dbtype="tinyint" precision="1" attributes="unsigned" phptype="integer" null="false" default="0" />
<!-- Good Practice for tracking -->
<field key="createdon" dbtype="datetime" phptype="datetime" null="true"/>
<field key="createdby" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" default="0" />
<field key="editedon" dbtype="datetime" phptype="datetime" null="true"/>
<field key="editedby" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" default="0" />
<!-- This is !IMPORTANT it links the two tables, base table to subordinate table NB 'id' is created automatically -->
<composite alias="linktable1totable2" class="table2Class" local="id" foreign="table2_table1_id" cardinality="many" owner="local" />
<aggregate alias="CreatedBy" class="modUser" local="createdby" foreign="id" cardinality="one" owner="foreign"/>
<aggregate alias="EditedBy" class="modUser" local="editedby" foreign="id" cardinality="one" owner="foreign"/>
</object>
<object class="table2Class" table="ypn_table2" extends="xPDOSimpleObject">
<field key="table2_table1_id" dbtype="int" precision="11" phptype="integer" null="false" default=""/>
<field key="table2_key" dbtype="varchar" precision="3" phptype="string" null="false" default=""/>
<field key="table2_field1" dbtype="text" phptype="string" null="false" default=""/>
<!-- Used by MigX -->
<field key="deleted" dbtype="tinyint" precision="1" attributes="unsigned" phptype="integer" null="false" default="0" />
<field key="published" dbtype="tinyint" precision="1" attributes="unsigned" phptype="integer" null="false" default="0" />
<!-- Good Practice for tracking -->
<field key="createdon" dbtype="datetime" phptype="datetime" null="true"/>
<field key="createdby" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" default="0" />
<field key="editedon" dbtype="datetime" phptype="datetime" null="true"/>
<field key="editedby" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" default="0" />
<!-- This is !IMPORTANT it links the two tables, subordinate table back to the base table NB 'id' is created automatically -->
<aggregate alias="linktable2totable1" class="table1Class" local="table2_table1_id" foreign="id" cardinality="one" owner="foreign" />
<aggregate alias="CreatedBy" class="modUser" local="createdby" foreign="id" cardinality="one" owner="foreign"/>
<aggregate alias="EditedBy" class="modUser" local="editedby" foreign="id" cardinality="one" owner="foreign"/>
</object>
</model>
by clicking 'Save schema' the schema-file should have been created. Test this by clicking 'Load schema'.
4. Parse Schema
Create xpdo-classes and maps from the schema by clicking 'parse Schema' under the tab 'parse Schema'.
5. Create Table(s)
Create tables from the schema by clicking 'create Tables' on the tab 'create Tables'. This should create the tables.
6. Create the Configuration
Go to the main-tab 'MIGX'
There should be an empty grid with some buttons.
Click 'Add Item'
In the opening window add:
Name: migxtable1
Click 'Done'
The newly new created record should now appear in the grid.
It is possible to edit this record and add grid-columns, tabs, and many other things by right-clicking on migxtable1 and choosing 'edit', but in this case it will be much quicker to import our example-configuration.
Right-Click migxtable1 and choose 'Export/Import'
Using cut-and-paste, replace the code in the field 'Json' with the following :
{
"formtabs":[
{
"MIGX_id":1,
"caption":"Table 1",
"print_before_tabs":"0",
"fields":[
{
"MIGX_id":1,
"field":"id",
"caption":"Id",
"description":"",
"description_is_code":"0",
"inputTV":"",
"inputTVtype":"",
"validation":"",
"configs":"",
"restrictive_condition":"",
"display":"none",
"sourceFrom":"config",
"sources":"",
"inputOptionValues":"",
"default":"",
"useDefaultIfEmpty":"0",
"pos":1
},
{
"MIGX_id":2,
"field":"table1_key",
"caption":"Table 1 Key",
"description":"",
"description_is_code":"0",
"inputTV":"",
"inputTVtype":"",
"validation":"",
"configs":"",
"restrictive_condition":"",
"display":"",
"sourceFrom":"config",
"sources":"",
"inputOptionValues":"",
"default":"",
"useDefaultIfEmpty":"0",
"pos":2
},
{
"MIGX_id":3,
"field":"table1_field1",
"caption":"Table 1 Field 1",
"description":"",
"description_is_code":"0",
"inputTV":"",
"inputTVtype":"",
"validation":"",
"configs":"",
"restrictive_condition":"",
"display":"",
"sourceFrom":"config",
"sources":"",
"inputOptionValues":"",
"default":"",
"useDefaultIfEmpty":"0",
"pos":3
},
{
"MIGX_id":4,
"field":"linktable1totable2",
"caption":"Linked Items",
"description":"",
"description_is_code":"0",
"inputTV":"",
"inputTVtype":"migxdb",
"validation":"",
"configs":"migxtable2",
"restrictive_condition":"[[migxIsNewObject]]",
"display":"",
"sourceFrom":"config",
"sources":"",
"inputOptionValues":"",
"default":"",
"useDefaultIfEmpty":"0",
"pos":4
}
],
"pos":1
}
],
"contextmenus":"update||duplicate||remove",
"actionbuttons":"addItem",
"columnbuttons":"",
"filters":"",
"extended":{
"migx_add":"Add Table 1 Entries",
"disable_add_item":"",
"add_items_directly":"",
"formcaption":"",
"update_win_title":"",
"win_id":"table1Unique",
"maxRecords":"",
"addNewItemAt":"bottom",
"multiple_formtabs":"",
"multiple_formtabs_label":"",
"multiple_formtabs_field":"",
"multiple_formtabs_optionstext":"",
"multiple_formtabs_optionsvalue":"",
"actionbuttonsperrow":4,
"winbuttonslist":"",
"extrahandlers":"",
"filtersperrow":4,
"packageName":"yourpackagename",
"classname":"table1Class",
"task":"migxtable1",
"getlistsort":"",
"getlistsortdir":"",
"sortconfig":"",
"gridpagesize":"",
"use_custom_prefix":"0",
"prefix":"",
"grid":"",
"gridload_mode":1,
"check_resid":1,
"check_resid_TV":"",
"join_alias":"linktable1totable2",
"has_jointable":"yes",
"getlistwhere":"",
"joins":"",
"hooksnippets":"",
"cmpmaincaption":"MigX Example - two linked tables",
"cmptabcaption":"Table 1",
"cmptabdescription":"Add\/edit Table 1 Items",
"cmptabcontroller":"",
"winbuttons":"",
"onsubmitsuccess":"",
"submitparams":""
},
"columns":[
{
"MIGX_id":1,
"header":"Id",
"dataIndex":"id",
"width":"",
"sortable":"false",
"show_in_grid":"0",
"customrenderer":"",
"renderer":"",
"clickaction":"",
"selectorconfig":"",
"renderchunktpl":"",
"renderoptions":"",
"editor":""
},
{
"MIGX_id":2,
"header":"Table 1 Key",
"dataIndex":"table1_key",
"width":"",
"sortable":1,
"show_in_grid":1,
"customrenderer":"",
"renderer":"",
"clickaction":"",
"selectorconfig":"",
"renderchunktpl":"",
"renderoptions":"",
"editor":""
},
{
"MIGX_id":3,
"header":"Table 1 Field 1",
"dataIndex":"table1_field1",
"width":"",
"sortable":1,
"show_in_grid":1,
"customrenderer":"",
"renderer":"",
"clickaction":"",
"selectorconfig":"",
"renderchunktpl":"",
"renderoptions":"",
"editor":""
},
{
"MIGX_id":4,
"header":"Linked Items",
"dataIndex":"linktable1totable2",
"width":"",
"sortable":"false",
"show_in_grid":1,
"customrenderer":"",
"renderer":"this.renderChunk",
"clickaction":"",
"selectorconfig":"",
"renderchunktpl":"[[migxLoopCollection?\n&packageName=`yourpackagename`\n&classname=`table2Class`\n&where=`{\"table2_table1_id\":\"[[+id]]\"}`\n&selectfields=`table2_key`\n&tpl=`@CODE:[[+table2_key]]`\n&outputSeparator=`, `\n]]",
"renderoptions":"",
"editor":""
}
]
}
Click 'Done'.
Check that this step has completed successfully by right-clicking on migxtable1 and choosing 'edit'. The content just loaded should now appear in the correct places under the appropriate tabs.
Now repeat the process for the second config entry, migxtable2.
Click 'Add Item'
In the opening window add:
Name: migxtable2
Click 'Done'
The newly new created record should now appear in the grid.
Right-Click migxtable2 and choose 'Export/Import'
Using cut-and-paste, replace the code in the field 'Json' with the following :
{
"formtabs":[
{
"MIGX_id":2,
"caption":"Table 2",
"print_before_tabs":"0",
"fields":[
{
"MIGX_id":1,
"field":"id",
"caption":"id",
"description":"",
"description_is_code":"0",
"inputTV":"",
"inputTVtype":"",
"validation":"",
"configs":"",
"restrictive_condition":"",
"display":"none",
"sourceFrom":"config",
"sources":"",
"inputOptionValues":"",
"default":"",
"useDefaultIfEmpty":"0",
"pos":1
},
{
"MIGX_id":2,
"field":"table2_key",
"caption":"Table 2 Key",
"description":"",
"description_is_code":"0",
"inputTV":"",
"inputTVtype":"",
"validation":"",
"configs":"",
"restrictive_condition":"",
"display":"",
"sourceFrom":"config",
"sources":"",
"inputOptionValues":"",
"default":"",
"useDefaultIfEmpty":"0",
"pos":2
},
{
"MIGX_id":3,
"field":"table2_field1",
"caption":"Table 2 Field 1",
"description":"",
"description_is_code":"0",
"inputTV":"",
"inputTVtype":"",
"validation":"",
"configs":"",
"restrictive_condition":"",
"display":"",
"sourceFrom":"config",
"sources":"",
"inputOptionValues":"",
"default":"",
"useDefaultIfEmpty":"0",
"pos":3
}
],
"pos":1
}
],
"contextmenus":"update||duplicate||remove",
"actionbuttons":"addItem",
"columnbuttons":"",
"filters":"",
"extended":{
"migx_add":"Add Table 2 Items",
"disable_add_item":"",
"add_items_directly":"",
"formcaption":"",
"update_win_title":"",
"win_id":"table2Unique",
"maxRecords":"",
"addNewItemAt":"bottom",
"multiple_formtabs":"",
"multiple_formtabs_label":"",
"multiple_formtabs_field":"",
"multiple_formtabs_optionstext":"",
"multiple_formtabs_optionsvalue":"",
"actionbuttonsperrow":4,
"winbuttonslist":"",
"extrahandlers":"",
"filtersperrow":4,
"packageName":"yourpackagename",
"classname":"table2Class",
"task":"migxtable2",
"getlistsort":"",
"getlistsortdir":"",
"sortconfig":"",
"gridpagesize":"",
"use_custom_prefix":"0",
"prefix":"",
"grid":"",
"gridload_mode":1,
"check_resid":1,
"check_resid_TV":"",
"join_alias":"linktable2totable1",
"has_jointable":"yes",
"getlistwhere":"",
"joins":"",
"hooksnippets":"",
"cmpmaincaption":"",
"cmptabcaption":"",
"cmptabdescription":"",
"cmptabcontroller":"",
"winbuttons":"",
"onsubmitsuccess":"",
"submitparams":""
},
"columns":[
{
"MIGX_id":1,
"header":"id",
"dataIndex":"id",
"width":"",
"sortable":"false",
"show_in_grid":"0",
"customrenderer":"",
"renderer":"",
"clickaction":"",
"selectorconfig":"",
"renderchunktpl":"",
"renderoptions":"",
"editor":""
},
{
"MIGX_id":2,
"header":"Table 2 Key",
"dataIndex":"table2_key",
"width":"",
"sortable":"false",
"show_in_grid":1,
"customrenderer":"",
"renderer":"",
"clickaction":"",
"selectorconfig":"",
"renderchunktpl":"",
"renderoptions":"",
"editor":""
},
{
"MIGX_id":3,
"header":"Table 2 Field 1",
"dataIndex":"table2_field1",
"width":"",
"sortable":"false",
"show_in_grid":1,
"customrenderer":"",
"renderer":"",
"clickaction":"",
"selectorconfig":"",
"renderchunktpl":"",
"renderoptions":"",
"editor":""
}
]
}
Click 'Done'.
Check that this step has completed successfully by right-clicking on migxtable2 and choosing 'edit'. The content just loaded should now appear in the correct places under the appropriate tabs.
7. Add a Menu Item
Go to Tools (gear icon)->Menus->
Click the 'Create Menu' button
Parent: choose where you would like the menu to appear
Lexicon-key: Migx linked tables
Action: index
Parameters: &configs=yourpackagename
Namespace: migx
Refresh the display, and the menu item you have just created should appear.
8. Add records to the tables
Click on 'Add Table 1 Entries'
Enter what you need and click 'Done'
The new record now appears in the grid.
Right-click on this record and choose 'Edit'.
You can now change the information that you have just entered, and click 'Done' OR at the bottom under 'Linked Items' you could click on 'Load Grid' This will load the grid of subordinate items.
To add items to this second table, click on 'Add Table 2 Items', enter the information and hit 'Done'. The new item appears in the subordinate grid.
Press 'Done' again will return you to the top level - note that the key that you just entered now appears under 'Linked Items'.
Cool !