[almost] AUTOMATIC TAB FORMS
Posted: 2016-06-28 15:26
I have coded a module that will, with two lines added to the tablename.php hook file, create tabbed forms.
There are some caveats, of course.
FIRST:
The fields in AppGini must be prefixed with the tab id. For example, lets say you have an address book and want to always show the name, and have address and phone in separate tabs.
Table: contacts
Fields:
id
name
addr_street
addr_unit
addr_city
addr_st
addr_zip
phone_home
phone_cell
phone_work
phone_fax
phone_other_name
phone_other
It is necessary for all fields in a tab to be grouped together as shown. In the example, the tab IDs are 'addr' and 'phone'.
Because the 'name' field has no prefix, it has no tab. However, it will end up in a tab called 'name', which is not what is desired. There's a way to handle this, of course, which leads to the second caveat.
SECOND:
Any fields named 'id' or '?????_id' (ending with _id) will be excluded from any tab. This is so they will display at the top of the form, above the tabs. You can, of course, exclude any fields you wish.
THIRD:
Sometimes the best tab ID isn't the best tab NAME. In the example, the 'addr' and 'phone' tab IDs become tab names 'Addr' and 'Phone'. While 'Phone' is probably okay, 'Addr' isn't the best choice.
There is a method provided for dealing with this. So, in AppGini, you can use short and simple abbreviations, but in the form you can have meaningful names.
HOW-TO:
Copy the code block at the bottom of this post into your hooks folder as 'hooks/_mktabbed.php'.
In the hooks/contacts.php file, insert the following into the contacts_dv function:
This pulls the code into the detail view function and then invokes it passing:
-- the table/form name
-- a string to remap the addr tab name to "Address info"
-- instructions to exclude the 'id' and 'name' fields from tabs
Note that if a field (such as id) is hidden from the detail view in AppGini, then it is not strictly necessary to exclude it from mktabbed(). On the other hand, it hurts nothing.
RESULTS:
Here is the resulting detail view.
SOURCE CODE for hooks/_mktabbed.php
There are some caveats, of course.
FIRST:
The fields in AppGini must be prefixed with the tab id. For example, lets say you have an address book and want to always show the name, and have address and phone in separate tabs.
Table: contacts
Fields:
id
name
addr_street
addr_unit
addr_city
addr_st
addr_zip
phone_home
phone_cell
phone_work
phone_fax
phone_other_name
phone_other
It is necessary for all fields in a tab to be grouped together as shown. In the example, the tab IDs are 'addr' and 'phone'.
Because the 'name' field has no prefix, it has no tab. However, it will end up in a tab called 'name', which is not what is desired. There's a way to handle this, of course, which leads to the second caveat.
SECOND:
Any fields named 'id' or '?????_id' (ending with _id) will be excluded from any tab. This is so they will display at the top of the form, above the tabs. You can, of course, exclude any fields you wish.
THIRD:
Sometimes the best tab ID isn't the best tab NAME. In the example, the 'addr' and 'phone' tab IDs become tab names 'Addr' and 'Phone'. While 'Phone' is probably okay, 'Addr' isn't the best choice.
There is a method provided for dealing with this. So, in AppGini, you can use short and simple abbreviations, but in the form you can have meaningful names.
HOW-TO:
Copy the code block at the bottom of this post into your hooks folder as 'hooks/_mktabbed.php'.
In the hooks/contacts.php file, insert the following into the contacts_dv function:
Code: Select all
function contacts_dv($selectedID, $memberInfo, &$html, &$args){
require('hooks/_mktabbed.php');
$html .= mktabbed('contacts', 'addr=Address info', 'id,name');
}
-- the table/form name
-- a string to remap the addr tab name to "Address info"
-- instructions to exclude the 'id' and 'name' fields from tabs
Note that if a field (such as id) is hidden from the detail view in AppGini, then it is not strictly necessary to exclude it from mktabbed(). On the other hand, it hurts nothing.
RESULTS:
Here is the resulting detail view.
SOURCE CODE for hooks/_mktabbed.php
Code: Select all
<?php
function mktabbed($table, $names="", $omit="id,.*_id") {
// no tabs in print preview
if(isset($_REQUEST['dvprint_x'])) return;
// clean up return from get_sql_fields() to create
// a list of field names as 'f1'f2'f3...'
$search = array ( "/,.*? as /" , "/''/" );
$replace = array ( "" , "'" );
$fieldnames = preg_replace($search, $replace, ",".get_sql_fields($table));
// drop any omitted fields (ie, omitted from tabs)
//
// by default, the primary key (id) and foreign keys
// (tablename_id) are omitted so they're not tabbed,
// but the $omit parameter can be used to change this
// (ie, drop other fields, or set to "" to drop none)
foreach (explode(",", $omit) as $field) {
$fieldnames = preg_replace("/'$field'/U", "'", $fieldnames);
}
// delete leading and trailing ' and explode into array
$fieldnames = preg_replace("/^'|'$/", "", $fieldnames);
$fields = explode("'", $fieldnames);
// build an associative array that separates fields by
// group, sets the tab name, and fields in the tab
$tabs=array();
$current="";
foreach ($fields as $field) {
// tab id is the chars up to the first _
$tab = preg_replace("/_.*/", "", $field);
if ($tab != $current) {
// replace the tab name if found in $names
$name = preg_replace("/.*,$tab=(.*?),.*/", "$1", ",$names,");
// if name still has a , in it, use the tab id
if (strpos($name, ",") !== false) $name=ucfirst($tab);
$tabs[$tab]['name'] = $name;
$tabs[$tab]['id'] = "{$tab}-info";
}
// append the field name to the fields array for the tab id
$tabs[$tab]['fields'][] = $field;
}
// what follows is basically what Ahmad provided in
// the Udemy course, but restructured a bit to allow
// it to be scripted a bit more cleanly
ob_start(); ?>
<div id="form-tabs">
<ul class="nav nav-tabs">
<?php
// we only want the first tab to be active
$first=true;
foreach ($tabs as $tab => $tabinfo) {
echo '<li '.(($first)?' class="active"':'')."><a href='#{$tabinfo[id]}' data-toggle='tab'>{$tabinfo[name]}</a></li>\n";
$first=false;
}
?>
</ul>
<ul class="tab-content">
<?php
// again, only the first panel is active
$first=true;
foreach ($tabs as $tab => $tabinfo) {
echo '<div class="tab-pane form-horizontal '.(($first)?' active':'').'" id="'.$tabinfo['id'].'"></div>'."\n";
$first=false;
}
?>
</ul>
</div>
<style>
#form-tabs .nav-tabs a{ display: block !important; }
</style>
<script>
$j(function(){
<?php
// here is where we move fields into tabs
echo "\$j('#form-tabs').appendTo('#{$table}_dv_form');\n";
foreach ($tabs as $tab => $tabinfo) {
foreach ($tabinfo['fields'] as $tabfield) {
echo "\$j('#{$tabfield}').parents('.form-group').appendTo('#{$tabinfo[id]}');\n";
}
}
?>
})
</script>
<?php
$html = ob_get_contents();
ob_end_clean();
return $html;
}