问题:
cppcms中form如何使用呢?官网上,除了教学篇-5之外,再无其他关于form使用的帮助文档了。当然,还有另外两种办法,就是看reference api文档和源代码。但是每次在使用form之前,或者长时间不用cppcms都使用后面两种办法自学的话,真是有点费劲费时。
小结:
基于上述问题原因,做了下面cppcms中form的小结,以便后续使用。
还是先看教学篇5的源代码,先看content.h。
#include <cppcms/view.h>
#include <cppcms/form.h>
namespace content {
struct info_form : public cppcms::form {
cppcms::widgets::text name;
cppcms::widgets::radio sex;
cppcms::widgets::select marital;
cppcms::widgets::numeric<double> age;
cppcms::widgets::submit submit;
info_form(){
name.message("Your Name");
sex.message("Sex");
marital.message("Marital Status");
age.message("Your Age");
submit.value("Send");
add(name);
add(sex);
add(marital);
add(age);
add(submit);
sex.add("Male", "male");
sex.add("Female", "female");
marital.add("Single", "single");
marital.add("Married", "married");
marital.add("Divorced", "divorced");
name.non_empty();
age.range(0, 120);
}
virtual bool validate(){
if(!form::validate())
return false;
if(marital.selected_id()!="single" && age.value()<18){
marital.valid(false);
return false;
}
return true;
}
};
struct message : public cppcms::base_content {
std::string name, state, sex;
double age;
info_form info;
};
}
照常例,使用cppcms时,都先准备content,同样我们定义一个message struct,template被填充message中的成员变量值。正如教学篇5中,页面只有一个简单的form,里面包含姓名(text)、性别(radio)、婚姻状况(select)、age(text),提交按钮(submit)五个form组件。
按照传统HTML页面来讲,当客户提交表单时,表单中信息均保存在http request中POST数组变量中。在cppcms中,我们可以通过使用http_request的post(std::string const &name)读取这些原始数据。以下,是我使用CPPCMS按照传统方式编写的一个简单表单交互测试。
1. 定义content.h
#ifndef CONTENT_H
#define CONTENT_H
#include <cppcms/view.h>
#include <cppcms/form.h>
namespace content {
struct message : public cppcms::base_content {
std::string name, state, sex;
double age;
};//end message
}// end content
#endif
2. 定义basicform view
<% c++ #include "content.h" %>
<% skin form_skin %>
<% view basicform uses content::message %>
<% template render() %>
<html>
<body>
<% if not empty name %>
<h1>Hi, <%= name %></h1>
<p>Your sex is <%= sex %>, and your marital status is <%= state %>.
<p>Your age is <%= age %>.</p>
<% else %>
<h1> Input Your Details </h1>
<form method="post" action="">
<p>Your name: <input type="text" name="name"></p>
<p>Sex: <input type="radio" name="sex" value="male">Male
<input type="radio" name="sex" value="female">Female</p>
<p>
Marital status: <select size="1" name="state">
<option value="single">Single</option>
<option value="married">Married</option>
<option value="divorced">Divorced</option>
</select>
</p>
<p>Your age: <input type="text" name="age"></p>
<p><input type="submit" value="Send"></p>
</form>
<% end %>
</body>
</html>
<% end template %>
<% end view %>
<% end skin %>
3. 编写controller,base_form.cpp
#include <cppcms/application.h>
#include <cppcms/applications_pool.h>
#include <cppcms/service.h>
#include <cppcms/http_request.h>
#include <cppcms/http_response.h>
#include <cppcms/url_dispatcher.h>
#include <cppcms/url_mapper.h>
#include <iostream>
#include "content.h"
using namespace std;
class hello : public cppcms::application{
public:
hello(cppcms::service &s):cppcms::application(s){}
void main(std::string){
content::message c;
if(request().request_method()=="POST"){
if(request().post("name")!=""){
c.name = request().post("name");
c.sex = request().post("sex");
c.state= request().post("state");
c.age = atoi(request().post("age").c_str());
render("basicform", c);
}
}
else
render("basicform", c);
}
};
int main(int argc, char **argv){
try{
cppcms::service app(argc, argv);
app.applications_pool().mount(cppcms::applications_factory<hello>());
app.run();
}
catch(std::exception const &e){
cerr<<e.what() << endl;
}
}
4. Makefile
CXX=g++ CPPCMSTMPL=cppcms_tmpl_cc LIBS=-lcppcms -lbooster all: clean hello_form hello_form: base_form.cpp basic_view.cpp content.h $(CXX) -Wall base_form.cpp basic_view.cpp -o hello_form ${LIBS} basic_view.cpp: base_form.tmpl content.h $(CPPCMSTMPL) base_form.tmpl -o basic_view.cpp clean: rm -rf hello_form basic_view.cpp
5. config.js
{ "service" : { "api" : "fastcgi", "ip" : "127.0.0.1", "port" : 9000 } }根据上述测试,不免有很多麻烦之处,比如在template中编写表单,在controller应用程序中,需要对表单的变量逐一进行解析。上述测试中,还没有加对表单数据的验证等。总之,编写起来比较繁琐。
不过,cppcms作者设计和实现了form的相关工具集用以解决传统表单交互的麻烦。
1. 在template中编写表单 —— 在cppcms template系统中定义了直接将form数据(model)转换成form视图(View)的构件(<% form as_p info %>),并且可以按照不同html_list_type方式形成不同类型的view.
2. 在content(model)中, 直接通过C++语言定义form表单,并且通过base_widgets类包包装了传统form的基础构件。其中新添加了numeric<T>组件,用以编制收集用户在表单输入数值,减少不必要的cast。另外,通过包装的widgets,还可以在此基础上,对用户录入数据进行验证。
3. widgets包装的每个form组件,都实现了load接口函数(纯虚函数,定义在base_form类中),这样用户只需要轻松调用load函数,实现request中表单数据的解析。
4. 通过form.h,即可看出cppcms眼中的form。一个form可以由多个sub-form组成,每个form都是由若干widget组成的。
因此,针对这样复杂的form,作者还提供了STL风格的form iterator,是不是很人性化啊。