Forms in CppCMS
Table of Contents
- Base Concepts
- Class form
- Class widgetset
- Widgets
- Dynamic Forms Creation
- Extending Unsupported Features
Basic Concepts
First of all, it is recommended to read a tutorial Start With Forms
Forms system of CppCMS has three major types of classes:
- Form -- cppcms::form--- the base class for form container, It is responsible on form validation, rendering. Usually, user derives its own classes fromcppcms::form
- Widgets in the namespace cppcms::widgets. They are basic elements of form like input text, number, checkbox, submit button etc.
- cppcms::widgetset--- simple class for partial rendering of forms for easier integration with templates.
All of them are derived from base_form that provide basic
interface for loading, rendering and validation of forms.
Class cppcms::form
This class used as base class for any HTML form developer wants to create. This class is non-copyable and used as container for loading, validating and rendering widgets.
Member functions
- void append(base_form *)register widget to the form.- When form is created every widget should be registered for validation and rendering. It can be done by calling - append()function.
- form &operator &(base_form &f)-- syntactic sugar for- append(). For example:- struct sum : public cppcms::form { widgets::number<int> M,N; widgets::submit button; my_form() : M("m","M"), N("n","N"), button("submit","Sum") { *this & M & N & button; } };- Now, when the form is rendered it is renders all widgets given in this list. 
- virtual void load(cgicc::Cgicc const &cgi)-- load form data for CGI environment. It is used when we need to load submitted data from user. For example:- if(env->getRequestMethod()=="POST") { sum.load(*cgi);
- virtual bool validate()-- validate loaded data. This method is always called after load. It is used for checking validity of all form widgets.- if(env->getRequestMethod()=="POST") { sum.load(*cgi); if(!sum.validate()) { // Process request } } // Continue with empty or partially filled form- This method is usually overridden for forms developer in order to implement advanced tests that are not available on widgets level. For example: - struct sum : public form { widgets::number<int> odd,even; ... virtual bool validate() { if(!form::validate()) return false; if(odd.get() % 2 == 1) return true; odd.not_valid(); return false; } };- When you re-implement validation, you should always perform base form validation and then perform your own tests. - Generally, best practice is performing all possible tests on form level, even complex things like keys validity and so on, in order make use of forms transparent for developer, i.e.: if form is valid then it is 100% valid. 
- void clear()--- reset the form, clear all widgets.
Class cppcms::widgetset
Is a container that is similar to form but it is used only
for rendering different types of widgets.
It has following important member function:
widgetset &operator<<(widgets::base_widget &w);
That allows registering of various widgets to the set. For example:
struct op {
  widgets::number<int> x,y;
  widgets::button add,sub,mul,div;
  widgetset inputs;
  widgetset ops;
  op() : 
    ...
  {
     *this & x & y & add & sub & mul & div;
     inputs<<x<<y;
     ops<<add<<sub<<mul<<div;
  }
};
Now can write template:
<table> <% form as_table ops_form.inputs %> </table> <p><% form as_space ops_form.ops %></p>
Now push buttons and input fields are rendered using different methods.
Widgets
Widgets are used for actual data loading and rendering. Each widget is derived from widgets::base_widget that hold all
common data for all widgets. It is also used for creation
of custom widgets by users.
Core Widget base_widget
Public Members
- bool is_set-- used to determinate whether this widget has assigned content. Usually it is set to- trueafter loading form with- form::load(). It is also set to true during manual assignment of value.
- string id-- HTML "id" of- inputtag. If it is empty, no HTML "id" is rendered. Generally used when user side validation is required.
- string name-- the "name" filed of HTML- inputtag. It is used for identifying data in forms. This member must be not-empty for correct form loading and rendering.
- string msg-- the message that describes the widget like "Username", "Password". Usually it should be provided.
- string error_msg-- the message that should be displayed for this widget if its input is invalid. If- error_msgis empty little start "*" is displayed.
- string help-- additional help string that can be displayed for the widget, usually it is expanded description of- msg.
- bool is_valid-- the flag that is used to check whether loaded widget has valid information.
Note: Generally you should not assign values of is_set
and is_valid directly. They are provided as
public members for simpler integration with template
system for custom widgets rendering.
Public Member Functions
- void not_valid()--- invalidate widget content. It is generally called after additional checks that are performed on form level.
Other functions would be described in section of custom widgets creation.
Text Input: widgets::text
This is text input widget.
- text(string name,string msg)-- creates text input widget with name and short description.
- set_limits(int min,int max)-- set limits on field size, where max=-1 --- no limit.
- set_nonempty()-- same as- set_limits(1,-1). This field should not be empty.
- set_limits(string error_message,int min,int max)-- Sets limits and a message that should be displayed in case of error.
- void set(string const &)-- set the value to this field.
- string const &get()-- get the values of this field.
- string &str()-- set value by reference. Is useful for reducing memory copying for big strings.- string text=get_text_from_db(); form.content.str().swap(text); 
- string value-- the content of the widget, you should never set its value directly! It may be used only for special form rendering, for example:- <input type="text" name="<% frm.msg.name %>" value="<% frm.msg.value %>" onclick="alert('Clicked!')" />- Which can't be rendered using normal - <% form as_p frm %>.- For any other purposes, use - set(),- get()and- str()member functions.
Numerical Input: widgets::number<>
This widget is defined as:
template<typename N>
number : public text { ... };
It is used as input for numerical values.
In addition to text members it implements following member functions:
- number(string name,string msg)-- constructor. It has same parameters as- text.
- void set_low(N a)-- set minimal allowed value for the number.
- void set_high(N a)-- set maximal allowed value;
- void set_range(N a,N b)--- same as- set_low(a),- set_high(b).
- N get() const--- returns widget value
- void set(N v)--- set initial value
Note: This widget uses boost::lexical_cast for conversion. Any type that is supported
by boost::lexical_cast is supported by number widget.
Password Input: widgets::password
Used for input password values. It inherits from widgets::text.
- password(string name,string msg)-- set name and message for password, similar for text widget.
- void set_equal(password &p2)-- adds additional validity check --- password confirmation.- Note: It stores a pointer to another password widget. So make sure, that other widget does not moved or get deleted. 
Text Area: widgets::textarea
Inherits from widgets::text.
- textarea(string name,string msg)-- same constructor as of- widgets::text.
- int rows,cols-- number of rows and columns of text area. Default is -1 --- undefined. You should set these values directly.
Complex Field Validation: widgets::regex_field
This widget allows you to check an input using regular expression. It uses boost::regex for this purpose.
It inherits from widgets::text as well.
- regex_field(boost::regex const &e,string name,string msg)-- create field using regular expression.
Note: You should provide regular expression of your own. For example:
static const regex date("\\d\\d-\\d\\d-\\d\\d\\d\\d");
regex_field date_input(date,"data","Enter Date");
Hidden Field: widgets::hidden
Hidden field can be used as widgets::hidden. This class inherits for widgets::text
and by default it is set to non-empty.
Check Box: widgets::checkbox
This widget renders a checkbox.
Constructor:
- checkbox(string name,string msg) -- construct checkbox using name. Default value for checkbox - valuefield is "1". Thus usually you distinguish several checkboxes using different names. For example:- checkbox has_car("car","Have Car"); checkbox married("married","Married");- Would cause following "GET" method url: - /?car=1&married=1
Members Functions:
- void set(string const &value)-- set the value for checkbox. For example:- vector<checkbox> options; for(i=0;i<choises.size();i++) { options.push_back(checkbox("opt",i)); }- That may generate following url: '/?opt=1&opt=2&opt=1' 
- void set(bool)-- set checked state.
- bool get()-- return whether this checkbox was checked or not.
Public Members For Form Rendering
Note: You should never set these members directly. You may use them only for form rendering:
- string input_value--- valuepart of input HTML element.
- bool value-- true if this checkbox should be "checked".
For example:
<intput name="<% form.opt.name %>" value="<% form.opt.input_value %>" 
  <% if form.opt.value %>checked="checked"<% end %> onclick="alert('Clicked!')" />
Single Choice Select
There are two widgets that are used for these purpose: select and radio that both
inherit from select_base.
select_base members
- void add(string value,string option)-- add a select option named- optionwith value- value.
- void add(string value)-- same as- add(value,value). Note, generally, the first is actual name used for internal option representation, the second one is how it is displayed --- option name is usually localized. So usually you call:- opts.add("apple",gettext("Apple"));
- void add(int value,string option)-- add a select option with numerical representation.
- void add(int value)--- same as- add(value,tostring(value)).
Usually you should use string values or integer values and not mix them.
- void set(string value)-- set selected value.
- void set(int value)-- set selected integer value.
- string get()-- get selected value. Note: if you used- add(int,string)you would get this option converted to string.
- int geti()-get integer value. If the option is textual, result is undefined.
Public members for rendering:
- struct option { string value,option; };-- internal representation of values.
- list<option> select_list-- list of available options.
- string value-- the selected value of option.
Both widgets::select and widgets::radio has following ordinary constructors:
- select(string name,string msg)
- radio(string name,string msg)
widgets::select members
- void set_size(int n)-- set number of lines for input drop-down list.
widgets::radio members
- void set_vertical()-- set vertical rendering of radio buttons list.
Multiple Selection widgets::select_multiple
Multiple selection drop down list:
Constructor
- select_multiple(string name,int rows,string msg="")-- creates multiple select widget that has- rowsinput rows.
Public Member Functions
- void add(string val,string opt,bool selected=false)-- add selection option with value- valand description- opt.
- void add(int val,string opt,bool selected=false)-- same as above but use integer value.
- void add(string v,bool s=false)-- same as- add(v,v,s)
- void add(int v,bool s=false)-- same as- add(v,tostring(v),s)
These functions are used similarly to those of select_base but they have selection marks options. Generally, you
should not use both add(int,...) and add(string,...).
- set<string> &get()-- returns set of selected options.
- set<int> geti()-- returns set of selected integer options.
- set_min(int n)-- set minimal number of options that should be selected.
Public Members for Form Rendering
- int size-- number of rows in select list
- set<string> chosen-- selected options.
- map<string,string> available-- set of all available options (first) and their names (second)
As in above cases these members may be used only for form rendering. Do not change them directly.
Submit Button: widgets::submit
- submit(string name,string button_value,string msg="")-- Creates button with text- button_value.
- bool pressed--- this flag is true if this button was pressed.
- string value--- value member that should be used only for rendering.
Note: This widget checks only name filed and ignores value that may be localized. Thus, you
should generally specify different names for different buttons:
remove("rem",gettext("Remove")),
save("save",gettext("Save"))
Dynamic Creation Of Forms
In many cases it is required to create forms on-the-fly according to data that should be used. This can be done simply --- all widgets are default and copy constructable and assignable --- thus you just can create STL collections of them.
However, you should remember, that when you register your widgets in cppcms::form or in cppcms::widgetset
you pass pointers to them and not their copies. Thus, be careful, make sure your widgets are
not copied to other place.
For example:
struct opts : public form {
  std::vector<widgets::checkbox> options;
  widgets::submit button;
  opts();
}
Wrong Code:
opts::opts() : button("send","Send")
{
  for(i=0;i<10;i++) {
    options.push_back(widgets::checkbox("option_"+lexical_cast<string>(i),
                                        "Chose "_lexical_cast<string>(i+1)));
    *this & options.back();
  }
  *this & button;
}
Correct Code:
opts::opts() : button("send","Send")
{
  options.resize(10);
  for(i=0;i<10;i++) {
    options[i]=widgets::checkbox("option_"+lexical_cast<string>(i),
                                 "Chose "_lexical_cast<string>(i+1)));
    *this & options[i]; // Now vector would not reallocate its members
  }
  *this & button;
}
Extending and Unsupported Features
If any of given widgets does not satisfy your needs you may:
- Create your own widgets. See, form.handform.cppfor examples.
- Use cgicclibrary directly without no restriction.
 
 