Form Widget
The Form widget can help you to create/setup and validate html forms. To use it, derive
your Widget from FormWidget and implement the following methods:
* form (to generate the html form)
* validate (to validate the input)
* setup (to setup initial form values)
The form will then call the method formname_submit(result) on your
controller once the widget has been submitted and validation has passed.
This behaviour can be changed if you overwrite the on_submit method.
Here is an example that will display a form that asks the user to enter a
string twice:
# We use the markaby generator
require 'form'
require 'cuca/generator/markaby'
class FormTestWidget < FormWidget
include Cuca::Generator::Markaby
# validate must set @form_errors on every element it noticed an error
def validate
@form_errors['input2'] = "You should enter #{params['input1']}" \
unless params['input1'] == params['input2']
end
def setup
@input1 = "Change me"
end
# this method will output the html form
def form
mab do
# FormErrorsWidget is another widget in the cuca collection that will
# display any form errors (setted by the validate method) nicely
FormErrors(@form_errors)
form(:name=>@form_name, :method=>'post') do
table { tr { td { "Enter something"}
td { input(:name=>'input1', :type=>'text',:value=>@input1) }
}
tr { td { "Enter Again" }
td { input(:name=>'input2', :type=>'password',:value=>@input2) }
}
tr { td {}
# You need to name your submit button @submit_name so
# the Widget can identify correctly if a form was
# submitted
td { input(:type=>'submit', :name=>@submit_name) }
}
}
end #form
end # mab
end
end
Our controller can be like this:
require 'cuca/generator/markaby'
class TestController < Cuca::Controller
include Cuca::Generator::Markaby
def test_submit(result)
mab { "Congratulations, you typed twice: '#{result['input1']}'" }
end
def run
mab { FormTest('test') }
end
end
The output will look like:
FormWidget with ActiveRecord
If you use ActiveRecord you can use
ARFormWidget to create forms for a Record.
ARForm will use ActiveRecord validations and the record layout to build the
form. If submitted and validated it will call formname_submit(model)
on the controller. Example:
Database Table:
CREATE TABLE users (
id serial unique,
username varchar(256),
account_id integer,
agent_id integer,
password varchar(256),
firstname varchar(256),
lastname varchar(256),
created timestamp default 'now',
enable boolean default 't',
user_type varchar(32) default 'USER' CHECK
(user_type IN ('ROOT', 'AGENT', 'USER'))
);
Our ActiveRecord Model:
class User < ActiveRecord::Base
validates_length_of :username, :within => 3..15
validates_uniqueness_of :username
# force created time to be right
def before_create
self.created = Time.now
end
end
Then, a "full featured" user-add controller could look like this:
class UserAddController < ApplicationController
def useradd_submit(user)
user.save!
session.flash[:message] = 'User Added'
stop :redirect=> "user/#{user.username}/"
end
def run
mab do
# we switch off the id and created field = they will be set
# automatically.
h1 { "Add a new user" }
ARForm('useradd', User.new, :disable_on_create => ['id', 'created'])
end
end
end
Your generated form will look like:
ARFormWidget with custom layout
To build your custom layout you have to derive a new class from ARForm and
overwrite the form method. To display the form elements
you should use the fe and fe_for methods. These methods
will return the right html code for the column type and possible with the
right values. Example:
class UserFormWidget < ARFormWidget
def output(form_name, model, options = {})
options[:disabled_on_create] = ['id', 'created']
super(form_name, model, options)
end
public
def form
r = mabtext { FormErrors(@form_errors) }
r << "<form action='#{@post_to}' method='POST'>\n"
r << " <table>"
r << " <tr><td>Username</td><td>#{fe_for('username')}</td></tr>"
r << " <tr><td>Password</td><td>#{fe(:password, 'password')}</td></tr>"
r << " <tr><td>Name</td><td>#{fe_for('firstname')} #{fe_for('lastname')}</td></tr>"
r << " <tr><td>Enabled</td><td>#{fe_for('enabled')}</td></tr>"
r << " <tr><td>Account created</td><td>#{fe_for('created')}</td></tr>"
r << " <tr><td>Account type</td><td>#{fe_select('user_type',['USER','AGENT','ROOT'], true)}</td></tr>"
r << " <tr><td></td><td><input type='submit' value=#{@model.new_record? ? 'Save' : 'Update'} name='#{@submit_name}'></td><tr>"
r << "</table>\n</form>\n"
@_content = r
end
end
Output of this form will look like:
ARForm for create and updates
ARForm can be used to create initial records and to update existing ones.
A user edit controller that reuses the above UserForm could be like this
this example:
class UsereditController < ApplicationController
def user_edit_submit(model)
model.save!
session.flash[:message] = "User updated!"
stop :redirect => "user/#{user.username}"
end
def run
@user = User.find(params['user_id'])
stop :error => "Unknown user" if @user.nil?
mab do
h1 { "Edit user #{@user.username}" }
UserForm('user_edit', @user)
end
end
end
...and you'll get a form with existing values ready to be updated.
<------ Back to Index