## Table of Contents
|
|
- [Base Concepts](#bc)
|
- [Class `form`](#c_form)
|
- [Class `widgetset`](#c_widgetset)
|
- [Widgets](#wid)
|
- [Base Widget](#wid_base)
|
- [Text Input](#w_text)
|
- [Password](#w_pass)
|
- [Text Area](#w_textarea)
|
- [Regular Expression Validation](#w_regex)
|
- [Hidden Field](#w_hidden)
|
- [Check Box](#w_cb)
|
- [Single Choise Selection](#w_select)
|
- [Multiple Choise Selection](#w_selectm)
|
- [Submit Button](#w_submit)
|
- [Dynamic Forms Creation](#dyn)
|
- [Extending Unsupported Features](#ext)
|
|
|
|
## <span id="bc"></span>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.
|
|
## <span id="c_form"></span>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.
|
|
## <span id="c_widgetset"></span>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.
|
|
## <span id="wid"></span>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.
|
|
### <span id="wid_base"></span>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.
|
|
### <span id="w_text"></span>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.
|
|
### <span id="w_pass"></span>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.
|
|
### <span id="w_textarea"></span>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.
|
|
|
### <span id="w_regex"></span>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");
|
|
### <span id="w_hidden"></span>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.
|
|
### <span id="w_cb"></span>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!')" />
|
|
### <span id="w_select"></span>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.
|
- **`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.
|
|
### <span id="w_selectm"></span>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.
|
|
### <span id="w_submit"></span>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"))
|
|
## <span id="dyn"></span>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;
|
}
|
|
## <span id="ext"></span>Extending and 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)
|
|