Bitrix Site Manager

Example: creating a custom editing form

You can view a working example of a custom Control Panel editing page in Example: creating a custom editing page.

Basic principles

The following functions are required to implement a Control Panel editing page:

API features designed for building the Control Panel pages allow to isolate the implementation of these functions. To give a user a better usability experience, forms should be split into pages with dynamic navigation using tabs.

Let us see how to create an editing form in the administration interface. We shall use the Newsletter module page as an example.

The beginning

First, create a file bitrix/modules/subscribe/rubric_edit.php as follows:


<?
// include all necessary files

// the first common prologue
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_before.php");

// initialise the module
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/subscribe/include.php");

// the module proloque
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/subscribe/prolog.php");

// include a language file
IncludeModuleLangFile(__FILE__);

// obtain the current user access level for the module
$POST_RIGHT = $APPLICATION->GetGroupRight("subscribe");

// if access is denied, direct the visitor to the authorization form
if ($POST_RIGHT == "D")
$APPLICATION->AuthForm(GetMessage("ACCESS_DENIED"));?> <? // prepare all data here ?> <? // the second common prologue
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php"); ?> <? // display page here ?> <?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_admin.php");?>

This is the page body indicated on the figure.

Now create a French language file, for example: /bitrix/modules/subscribe/lang/ru/rubric_edit.php. In this file, create all language messages as the array elements: $MESS['message_identifier'] = "message_text";.

Since the /bitrix/modules/ catalog is not accessible via HTTP as has been set by the BSM installation, create a file /bitrix/admin/rubric_edit.php:


<?
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/subscribe/admin/rubric_edit.php");
?>

Now this file is available here: http://mysite.ru/bitrix/admin/rubric_edit.php.

Page functions

As the figure illustrates, all page functions can be relatively divided into the following steps:

For this, we need instances of the following classes.

Class Description
CAdminTabControl Displays the form split into pages with dynamic tabs.
CAdminMessage Used with administration messages.
CAdminContextMenu Used with the Control Panel action toolbars.
Handling and preparing data
Configuring the tabbed interface

A Control Panel form can be split into tabbed pages. To define the tab layout, you have to create an array whose elements are associated arrays with the following keys.

Key Description
DIV The unique tab ID.
TAB The tab text.
TITLE Describes the page to which the tab is linked.
ICON The CSS class of an icon to be displayed near the page title.
ONSELECT JavaScript function to be executed when a user clicks the tab.

Now, we have to create a CAdminTabControl class instance passing this structure to the class constructor.


$aTabs = array(
  array("DIV" => "edit1", 
        "TAB" => GetMessage("rub_tab_rubric"),
        "ICON"=>"main_user_edit",
        "TITLE"=>GetMessage("rub_tab_rubric_title")), array("DIV" => "edit2",
        "TAB" => GetMessage("rub_tab_generation"),
        "ICON"=>"main_user_edit",
        "TITLE"=>GetMessage("rub_tab_generation_title")), );
$tabControl = new CAdminTabControl("tabControl", $aTabs);
Handling and saving changes

First, define variables for later use:


// the identifier of a record to be edited
$ID = intval($ID);
// error message
$message = null;
// this flag indicates that the data was obtained via the form rather than database
$bVarsFromForm = false;

The form dirty state can be determined using the following parameters:

If one of these conditions are true and security checks are passed, we can save the data that has been passed to the script:


if(
    $REQUEST_METHOD == "POST" // check the page call method
    &&
    ($save!="" || $apply!="") // check Save and Apply buttons
    &&
    $POST_RIGHT=="W"          // check the access permission for the module
    &&
    check_bitrix_sessid()     // check the session identifier
)
{
  $rubric = new CRubric;
  
  // process the form data
  $arFields = Array(
    "ACTIVE"         => ($ACTIVE <> "Y" ? "N" : "Y"),
    "NAME"           => $NAME,
    "SORT"           => $SORT,
    "DESCRIPTION"    => $DESCRIPTION,
    "LID"            => $LID,
    "AUTO"           => ($AUTO <> "Y" ? "N" : "Y"),
    "DAYS_OF_MONTH"  => $DAYS_OF_MONTH,
    "DAYS_OF_WEEK"   => (is_array($DAYS_OF_WEEK) ? implode(",", $DAYS_OF_WEEK) : ""),
    "TIMES_OF_DAY"   => $TIMES_OF_DAY,
    "TEMPLATE"       => $TEMPLATE,
    "VISIBLE"        => ($VISIBLE <> "Y" ? "N" : "Y"),
    "FROM_FIELD"     => $FROM_FIELD,
    "LAST_EXECUTED"  => $LAST_EXECUTED
  );

  // save the data
  if($ID > 0)
  {
    $res = $rubric->Update($ID, $arFields);
  }
  else
  {
    $ID = $rubric->Add($arFields);
    $res = ($ID > 0);
  }

  if($res)
  {
    // if saved ok, direct to a new page
    // (to prevent repeated form posts by clicking "Refresh" in a browser)
    if ($apply != "")
      // if Apply is clicked, navigate back to the form.
      LocalRedirect("/bitrix/admin/rubric_edit.php?ID=".$ID."&mess=ok&lang=".LANG."&".$tabControl->ActiveTabParam());
    else
      // if Save is clicked, open the list of elements.
      LocalRedirect("/bitrix/admin/rubric_admin.php?lang=".LANG);
  }
  else
  {
    // if an error occurred, 
    // obtain the error message and modify the above variables if($e = $APPLICATION->GetException()) $message = new CAdminMessage(GetMessage("rub_save_error"), $e); $bVarsFromForm = true; } }
Selecting and preparing form data

First, define the default values. All data received form the database will be saved in the str_ variables.


$str_SORT          = 100;
$str_ACTIVE        = "Y";
$str_AUTO          = "N";
$str_DAYS_OF_MONTH = "";
$str_DAYS_OF_WEEK  = "";
$str_TIMES_OF_DAY  = "";
$str_VISIBLE       = "Y";
$str_LAST_EXECUTED = ConvertTimeStamp(false, "FULL");
$str_FROM_FIELD    = COption::GetOptionString("subscribe", "default_from");

Extract data:


if($ID>0)
{
  $rubric = CRubric::GetByID($ID);  
  if(!$rubric->ExtractFields("str_"))
    $ID=0;
}

Prepare the data and specify the page title:


// if the data came from the form, initialise it
if($bVarsFromForm)
  $DB->InitTableVarsForEdit("b_list_rubric", "", "str_");

$APPLICATION->SetTitle(($ID>0? GetMessage("rub_title_edit").$ID : GetMessage("rub_title_add")));
Configuring the Control Panel menu parameters

If required, you can assign the Control Panel menu which is displayed above the table (for users having the editing permissions). The menu is created as an array whose elements are associated arrays with the following keys:

Key Description
TEXT The menu item text.
TITLE The text of the menu item toolbar.
LINK The button link.
LINK_PARAM Additional link parameters (will be added to the <A> tag).
ICON The button CSS class.
HTML Specifies the menu item HTML code.
SEPARATOR Specifies that an item is a separator (true|false).
NEWBAR Starts a new block of menu items (true|false).
MENU Creates a drop down menu.
The value is specified similarly to the table row context menu.

Example:


$aMenu = array(
  array(
    "TEXT"  => GetMessage("rub_list"),
    "TITLE" => GetMessage("rub_list_title"),
    "LINK"  => "rubric_admin.php?lang=".LANG,
    "ICON"  => "btn_list",
  )
);

if($ID>0)
{
  $aMenu[] = array("SEPARATOR"=>"Y");
  
  $aMenu[] = array(
    "TEXT"  => GetMessage("rub_add"),
    "TITLE" => GetMessage("rubric_mnu_add"),
    "LINK"  => "rubric_edit.php?lang=".LANG,
    "ICON"  => "btn_new",
  );
  $aMenu[] = array(
    "TEXT"  => GetMessage("rub_delete"),
    "TITLE" => GetMessage("rubric_mnu_del"),
    "LINK"  => "javascript:if(confirm('".GetMessage("rubric_mnu_del_conf")."')) ".
	       "window.location='rubric_admin.php?ID=".$ID.
               "&action=delete&lang=".LANG."&".bitrix_sessid_get()."';", "ICON" => "btn_delete", ); $aMenu[] = array("SEPARATOR"=>"Y"); $aMenu[] = array( "TEXT" => GetMessage("rub_check"), "TITLE" => GetMessage("rubric_mnu_check"), "LINK" => "template_test.php?lang=".LANG."&ID=".$ID ); }

The resulting structure is passed to the CAdminContextMenu constructor.

Data output

As the figure shows, the page preparation and the main output must be separated by including the system file prolog_admin_after.php:


// don't forget to separate data preparation from presentation
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php");

First, display the prepared administration menu.


// create an instance of the Control Panel menu class
$context = new CAdminContextMenu($aMenu);

// emit the menu
$context->Show();

Display error or success messages, if any.


if($_REQUEST["mess"] == "ok" && $ID>0)
  CAdminMessage::ShowMessage(array("MESSAGE"=>GetMessage("rub_saved"), "TYPE"=>"OK"));

if($message)
  echo $message->Show();
elseif($rubric->LAST_ERROR!="")
  CAdminMessage::ShowMessage($rubric->LAST_ERROR);

Now print the form. Use CAdminTabControl::Begin to initialise the tab engine and display the tab bar. CAdminTabControl::BeginNextTab is used to end a current tab and start a new tab. CAdminTabControl::End closes all tabs.


<form method="POST" Action="<?echo $APPLICATION->GetCurPage()?>" ENCTYPE="multipart/form-data" name="post_form">
<?// check the session identifier ?>
<?echo bitrix_sessid_post();?>
<input type="hidden" name="lang" value="<?=LANG?>">
<?if($ID>0 && !$bCopy):?>
  <input type="hidden" name="ID" value="<?=$ID?>">
<?endif;?>
<?
// display tab titles
$tabControl->Begin();
?>
<?
//********************
// the first tab - an editing form of mail list parameters
//********************
$tabControl->BeginNextTab();
?>
  <tr>
    <td width="40%"><?echo GetMessage("rub_act")?></td>
    <td width="60%"><input type="checkbox" name="ACTIVE" value="Y"
      <?if($str_ACTIVE == "Y") echo " checked"?> /></td> </tr> <!-- HTML code of the table rows --> <tr> <td><?echo GetMessage("rub_auto")?></td> <td><input type="checkbox" name="AUTO" value="Y"
        <?if ($str_AUTO == "Y") echo " checked"?>            OnClick="if(this.checked) tabControl.EnableTab('edit2');
          else
              tabControl.DisableTab('edit2');" /></td> </tr> <? //******************** // the second tab - automated mail list parameters //******************** $tabControl->BeginNextTab(); ?> <tr class="heading"> <td colspan="2"><?echo GetMessage("rub_schedule")?></td> </tr> <tr> <td width="40%"><span class="required">*</span><?echo GetMessage("rub_last_executed"). " (".FORMAT_DATETIME."):"?></td> <td width="60%"><?echo CalendarDate("LAST_EXECUTED", $str_LAST_EXECUTED, "post_form", "20")?></td> </tr> <!-- HTML code of the table rows --> <tr> <td><span class="required">*</span><?echo GetMessage("rub_post_fields_from")?></td> <td><input type="text" name="FROM_FIELD" value="<?echo $str_FROM_FIELD;?>" size="30" maxlength="255" /></td> </tr> <? // close the form: display save and apply controls $tabControl->Buttons( array( "disabled"=>($POST_RIGHT<"W"), "back_url"=>"rubric_admin.php?lang=".LANG, ) ); ?> <? // complete the tabs $tabControl->End(); ?>

As the figure shows, a connection can be established between the form fields and the error messages, which will display messages about the fields whose values are incorrect.


<?
// additional errors messages displayed besides the field where an error occured
$tabControl->ShowWarnings("post_form", $message);
?>

You can also control the tab behaviour via JavaScript. Consider the following example of disabling a tab:


<script language="JavaScript">
<!--
  if(document.post_form.AUTO.checked)
    tabControl.EnableTab('edit2');
  else
    tabControl.DisableTab('edit2');
//-->
</script>

Display the following notification after the table:


<?echo BeginNote();?>
<span class="required">*</span><?echo GetMessage("REQUIRED_FIELDS")?>
<?echo EndNote();?>

<?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_admin.php");?>

Here you can find the complete example of an administration page with the list.