Main  /  Edit version 6  /  Edit version 7  /   /  Users Area

Difference "Forms in CppCMS" ver. 6 versus ver. 7

Content:

## Basic Concepts
## 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.
## Class cppcms::form
## <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.
## Class cppcms::widgetset
## <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.
## Widgets
## <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.
### Core Widget `base_widget`
### <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.
### Text Input: `widgets::text`
### <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.
### Password Input: `widgets::password`
### <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.
### Text Area: `widgets::textarea`
### <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.
### Complex Field Validation: `widgets::regex_field`
### <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");
### Hidden Field: `widgets::hidden`
### <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.
### Check Box: `widgets::checkbox`
### <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!')" />
### Single Choice Select
### <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.
- **`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`
### <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.
### Submit Button: `widgets::submit`
### <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"))
## Dynamic Creation Of Forms
## <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;
}
## Unsupported Features
## <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)

About

CppCMS is a web development framework for performance demanding applications.

Support This Project

SourceForge.net Logo

Поддержать проект

CppCMS needs You


Navigation

Main Page


Valid CSS | Valid XHTML 1.0