Creating a form

In order to create a form you will need to:

Place for each form's files is directory hidden/inc/forms/. When you create a form you need to create subdir and store your files in there. For example files for form "user" will have to be placed in hidden/inc/forms/user/. Please note that this is not mandatory requirement but makes things much easier and tidy when site grows up and contains multiple forms (on really big sites sometimes additional grouping is used, e.g. all user related forms are stored in separate directory, thus "user" will be like hidden/inc/forms/user/user/).

Defining the form

We will use an example to demonstrate how to define form.

There are two base classes for forms that can be used:

  • Form
  • Guardable_Form - enhances Form by adding protection against double submit (when impatient one "pumps" on submit button multiple times)

Almost always Guardable_Form is used in TF sites.

Let's suppose that we want to create form for editing user:

  • username - string
  • password - string

We will name our form "user". First we have to create its directory hidden/inc/forms/user/.

In its directory we have to create file for the form. Name it user_form.class.php. Content for the file:

<?php

require_once(TANGRA_MAIN_DIR.'form/guardable_form.class.php'); // getting Guardable_Form class
require_once(TANGRA_MAIN_DIR.'form/fields/text/form_field_text.class.php'); // form field text
require_once(TANGRA_MAIN_DIR.'form/fields/password/form_field_password.class.php'); // form field date
require_once(TANGRA_MAIN_DIR.'/form/static_html_form_generator.class.php'); // generator for the HTML code


class User_Form extends Guardable_Form {
    function 
__construct() {
        
parent::__construct('user''user_edit.php');

        
// creating and adding username field to form
        
$f_username = new Form_Field_Text('username'true45); // field named 'username', mandatory = true, 45 characters max
        
$this->add_field($f_username);

        
// creating and adding password field
        
$f_password = new Form_Field_Password('password'true45);
        
$this->add_field($f_password);
    }


    public function 
generate_html() { // used just once to generate form's HTML
        // Static_HTML_Form_Generator is initialized with form, path to HTML template that will be used to generate the form, language to be used
        
$html_gen = new Static_HTML_Form_Generator($this'modules/form_html_tpl_static_ajax_metallic_en''en');
        
$html_gen->create_default_tpl_maps(); // creating mapping for field-to-template correspondence

        
printbr('<pre>');
        
printbr(htmlentities($html_gen->get_static_html())); // showing generated HTML
        
printbr('</pre>');
    }
}

For list of available form fields and their constructor's parameters please check » API reference.

Defining the form view

Next we have to define form view class in user_form_view.class.php. We have to create and add field view per each form field:

<?php

require_once(TANGRA_MAIN_DIR.'form/fields/text/form_field_text_view.class.php');
require_once(
TANGRA_MAIN_DIR.'form/fields/password/form_field_password_view.class.php');
require_once(
TANGRA_MAIN_DIR.'form/guardable_form_view.class.php');


class 
User_Form_View extends Guardable_Form_View {
    function 
__construct(Form &$form) {
        
parent::__construct($form);

        
// creating and adding view for username        
        
$f_username $form->get_field('username');
        
$f_username_view = new Form_Field_Text_View($form->get_name().'_'.$f_username->get_name(), $f_username);
        
$this->add_field_view('username'$f_username_view);

        
// creating and adding view for password
        
$f_password $form->get_field('password');
        
$f_password_view = new Form_Field_Text_View($form->get_name().'_'.$f_password->get_name(), $f_password);
        
$this->add_field_view('password'$f_password_view);
    }
}

Defining form controller

It is time to define the form controller. Form controller is the link between form, view and the model. We will use User class from previous section (Chapter 11, DBC classes). user_form_ctrl.class.php:

<?php

require_once(TANGRA_MAIN_DIR.'form/gform_ctrl_with_obj.class.php');

require_once(
'user_form.class.php');
require_once(
'user_form_view.class.php');

require_once(
$WSC->get_site_inc_dir().'classes/user/user_dbc.class.php');


class 
User_Form_Ctrl extends GForm_Ctrl_With_Object {
    protected function 
create_form() {
        
$form = new User_Form(); // instantiating form

//        $form->generate_html();
        
return $form;
    }


    protected function 
create_form_view() {
        
$ret = new User_Form_View($this->form); // instantiating form view

        
return $ret;
    }


    protected function 
on_good_submit() {
        
$ret true;

        return 
$ret;
    }


    protected function 
on_bad_submit() {

    }


    protected function 
create_object() { // creating object
        
$object = new User_DBC();

        return 
$object;
    }


    protected function 
transfer_obj2form() { // transferring values from object to form
        
$object $this->get_object();
        
$form $this->get_form();

        
$form->set_field_value('username'$object->get_username());
        
$form->set_field_value('password'$object->get_password());
    }


    protected function 
transfer_form2obj() { // transferring values from form to object
        
$object $this->get_object();
        
$form $this->get_form();

        
$object->set_username($form->get_field_value('username'));
        
$object->set_password($form->get_field_value('password'));
    }
}

Creating WP that will handle the form

WP file (hidden/inc/pages/user_edit_wp.class.php):

<?php

require_once($WSC->get_site_inc_dir().'site_page_w_fctrl.class.php');
require_once(
$WSC->get_site_inc_dir().'forms/user/user_form_ctrl.class.php');


class 
User_Edit_WP extends Site_Page_W_FCtrl {
    public function 
init() {
        
parent::init();

        
$view $this->get_view();
        
$view->add_css('modules/form_html_tpl_static_ajax_metallic/form.css'); // adding css for forms
    
}


    protected function 
create_form_ctrl() { // instantiating form controller
        
$dbc $this->create_dbc();
        
$tvm $this->get_tvm();
        
$ret = new User_Form_Ctrl('user'$tvm$dbc);

        return 
$ret;
    }
}

Defining AJAX controller

Ajax controller (hidden/inc/forms/user/user_form_ajax_ctrl.class.php):

<?php

require_once($WSC->get_site_inc_dir().'modules/jabba_ajax_form_ctrl/jabba_ajax_form_ctrl_with_object.class.php');
require_once(
$WSC->get_site_inc_dir().'forms/user/usere_form_ctrl.class.php');


class 
User_Form_Ajax_Ctrl extends Jabba_Ajax_Form_Ctrl_With_Object {
    protected function 
on_good_submit() {
        
$redir = new Redirect_Composer_Local($this->get__context(), 'site/site_manage.php');
        
$location $redir->get_target_address($this->get__context());

        
$ret = array('command' => Ajax_Ctrl::COMMAND_REDIRECT'command_value' => $location);

        return 
$ret;
    }


    protected function 
on_bad_submit() {
        return 
true;
    }


    protected function 
create_form_ctrl() {
        
$tvm $this->get_tvm();
        
$dbc $this->create_dbc();

        
$ret = new User_Form_Ctrl('user'$tvm$dbc);

        return 
$ret;
    }

}

Defining AJAX interceptor

Ajax interceptor (htdocs/ajax/user_form.php):

<?php

require_once('../../boot.inc.php');
boot('my_site_adm');

require_once(
$WSC->get_site_inc_dir().'forms/user/user_form_ajax_ctrl.class.php');


session_start();

global 
$_MODULES_REGISTER;
$user_auth_config $_MODULES_REGISTER->get_module_config('admin_user_auth');

$f_ajax_ctrl = new User_Form_Ajax_Ctrl($WSC->get_tpl_dir().'forms/user_form.tpl'$user_auth_config);
$context = new Web_Context();
$SITE->run_other($f_ajax_ctrl$context);

Creating TPL files

Create TPL files hidden/tpl/pages/user_edit/user_edit_title_en.tpl and hidden/tpl/pages/user_edit/user_edit_default_en.tpl. For title put "Editing user", leave user_edit_default_en.tpl empty for now.

Now we have to generate form's HTML. Go to user_form_ctrl.class.php and in create_form method uncomment row $form->generate_html();. Now point your browser to http://tft.myhost/user_edit.php?user_obj_id=1. You should see generated HTML. Select, copy and paste it in hidden/tpl/pages/user_edit/user_edit_default_en.tpl. Go back to user_form_ctrl.class.php and comment the row $form->generate_html();.

Now we have to create TPL files for form. Create hidden/tpl/forms/user_form.tpl with content:

{include file="forms/`$_language`/user/user_form_`$_language`.tpl"}

            

Create file (and necessary dir "user") hidden/tpl/forms/en/user/user_form_en.tpl. Go to hidden/tpl/pages/user_edit/user_edit_default_en.tpl and find <!-- *** CUT top -->. Select to (inclusive) <!-- *** CUT bottom -->, cut and paste in hidden/tpl/forms/en/user/user_form_en.tpl. In the place of cutted content in hidden/tpl/pages/user_edit/user_edit_default_en.tpl put {include file="forms/user_form.tpl"} so it looks like:

...
<div id="user_form_div" style="width:800px;">
{include file="forms/user_form.tpl"}
</div>
...

            

Test the form

Point your browser to http://tft.myhost/user_edit.php?user_obj_id=1 and you should see your form populated with data of user with ID = 1. Change some of the fields and click user_submit which will save the record (you can change the label of the button by editing hidden/tpl/pages/user_edit/user_edit_default_en.tpl. By default label "Save" is used).

Figure 12.1. User form

User form

Note: Cancel button will not work until you provide URL for cancel landing page. In order to to that find <a href="{$user_cancel_link}">Cancel</a> and change it.

WPs descentands of Site_Page_W_FCtrl take following GET parameters:

  • form_name_add_new=1, where form_name is the name of your form. This instructs the WP (and form controller) that you are about to add new record.
  • form_name_obj_id=ID, where ID is the ID of DB record to be loaded. This instructs the WP to load existing record in order to be edited. In case that there is no record with such ID - exception will be thrown.