## Basic Concepts |
|
First of all, it is recommended to read a tutorial [Start With Forms](/wikipp/en/page/tut_forms) |
|
Forms system of CppCMS has three major types of classes: |
|
1. Form -- `cppcms::form` --- the base class for form container, It is responsible on form validation, rendering. Usually, user derives its own classes from `cppcms::form` |
2. Widgets in the namespace `cppcms::widgets`. They are basic elements of form like input text, number, checkbox, submit button etc. |
3. `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 `true` after loading form with `form::load()`. It |
is also set to true during manual assignment of value. |
- **`string id`** -- HTML "id" of `input` tag. If |
it is empty, no HTML "id" is rendered. Generally used when |
user side validation is required. |
- **`string name`** -- the "name" filed of HTML `input` tag. |
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_msg` is 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` |
### 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 `value` field |
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`** -- `value` part 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 `option` with 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 `rows` input rows. |
|
#### Public Member Functions |
|
- **`void add(string val,string opt,bool selected=false)`** -- add selection option with value `val` and 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; |
} |
|
## Unsupported Features |
|
If any of given widgets does not satisfy your needs you may: |
|
1. Create your own widgets. See, `form.h` and `form.cpp` for examples. |
2. Use `cgicc` library directly without no restriction. |
|
See [CgiCC Documentation](http://www.gnu.org/software/cgicc/doc/index.html) |
|