理解cppcms中的form

问题:

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,是不是很人性化啊。

 

你可能感兴趣的:(form)