HTML::FormFu::ExtJS
version 0.090
This module allows you to render ExtJS forms without changing your HTML::FormFu config file.
use HTML::FormFu::ExtJS; my $form = new HTML::FormFu::ExtJS; $form->load_config_file('forms/config.yml'); print $form->render;
HTML::FormFu::ExtJS subclasses HTML::FormFu therefore you can access all of its methods via $form.
$form
If you want to generate grid data and data records for ExtJS have a look at HTML::FormFu::ExtJS::Grid.
This module requires ExtJS 2.2 or greater. Most of the elements work with ExtJS 2.0 or greater too.
This module is fully compatible with ExtJS 3.0.
HTML::FormFu::ExtJS - Render and validate ExtJS forms using HTML::FormFu
Check out the examples in examples/html
examples/html
or online at [ Examples ]
A HTML::FormFu::ExtJS object inherits all methods of a HTML::FormFu object. There are some additional methods avaiable:
Returns a full ExtJS form panel. Usually you'll use it like this (TT example):
var form = [% form.render %];
You can pass custom attributes to this method which are added to the form config.
var form = [% form.render(renderTo = 'main') %];
This will add a renderTo attribute to the form config.
renderTo
form is now a JavaScript object of type Ext.FormPanel. You might want to put a handler on the button so they will trigger a function when clicked.
form
Ext.FormPanel
Ext.getCmp("id-of-your-button").setHandler(function() { alert('clicked') } );
Or you can add the handler directly to your element:
- type: Button value: Handler attrs: handler: function() { alert("click") }
This methods returns data in a format which is expected by ExtJS as perl object. You will want to serialize it with JSON and send it to the client.
$form->grid_data($data);
$data can be a DBIx::Class::ResultSet object, an arrayref of DBIx::Class::Row objects or a simple perl object which should look like this:
$data
$data = [{fieldname1 => 'value1', fieldname2 => 'value2'}];
The returned perl object looks something like this:
{ 'metaData' => { 'fields' => [ { 'name' => 'artistid', 'type' => 'string' }, { 'name' => 'name', 'type' => 'string' } ], 'totalProperty' => 'results', 'root' => 'rows' }, 'rows' => [ { 'artistid' => '1', 'name' => 'Caterwauler McCrae' }, { 'artistid' => '2', 'name' => 'Random Boy Band' }, { 'artistid' => '3', 'name' => 'We Are Goth' } ], 'results' => 3 }
The metaData property does some kind of magic on the client side. Read http://extjs.com/deploy/dev/docs/?class=Ext.data.JsonReader for more information.
metaData
Sometimes you need to send a different number of results back to the client than there are rows (e. g. paged grid view). Therefore you can override every item of the perl object by passing a hashref.
$form->grid_data($data, {results => 99});
This will set the number of results to 99.
Notice:
This method is considered experimental. This is due to the fact that is pretty slow at the moment because of all the de- and inflation and accessing DBIC accessors. Future plans include that this module will be ORM independant and accepts Hashrefs only. This implies that you use DBIx::Class::ResultClass::HashRefInflator or anything similar if you want to use this method.
grid_data
record returns a JavaScript string which creates a Ext.data.Record object from the $form object. This is useful if you want to create Ext.data.Record objects dynamically using JavaScript.
record
Ext.data.Record
You can add more fields by passing them to the method.
$form->record(); # Ext.data.Record.create( [ {'name' => 'artistid', 'type' => 'string'}, # {'name' => 'name', 'type' => 'string'} ] ); $form->record( 'address', {'name' => 'age', type => 'date'} ); # Ext.data.Record.create( [ {'name' => 'artistid', 'type' => 'string'}, # {'name' => 'name', 'type' => 'string'}, # {'name' => 'age', 'type' => 'date'}, # 'address' ] );
To get the inner arrayref as perl object, call $form->_record().
$form->_record()
This method returns all form elements in the JavaScript Object Notation (JSON). You can put this string right into the items attribute of your ExtJS form panel.
items
Fields with the omit_rendering attribute set to a true value are not rendered, they are ignored. This feature is usefull if you have fields that are autogenerated on the client side.
omit_rendering
Acts like "render_items" but returns a perl object instead.
Renders a single element.
render_buttons returns all buttons specified in $form as a JSON string. Put it right into the buttons attribute of your ExtJS form panel.
render_buttons
buttons
Acts like "render_buttons" but returns a perl object instead.
Returns the validation response ExtJS expects as a perl Object. If the submitted values have errors the error strings are formatted returned as well. Send this object as JSON string back to the user if you want ExtJS to mark the invalid fields or to report a success.
If the submission was successful the response contains a data property which contains all submitted values.
data
Examples (JSON encoded):
{ "success" : false, "errors" : [ { "msg" : "This field is required", "id" : "field" } ] } { "success" : true, "data" : { field : "value" } }
A column model is required to render a grid. It contains all columns which should be rendered inside the grid. Those can be hidden or visible. A hidden form element will also result in a hidden column.
A field which has options (like HTML::FormFu::Element::Select) will create two columns.
Example:
--- default_model: HashRef elements: - type: Radiogroup label: Sex name: sex options: - [0, 'male'] - [1, 'female']
This will create the following columns:
{ 'dataIndex' : 'sexValue', 'hidden' : true, 'id' : 'sex-value', 'header' : 'Sex' }, { 'dataIndex' : 'sex', 'id' : 'sex', 'header' : 'Sex' }
The first column is hidden and contains the value of the select box (e. g. 0 or 1). The second column contains the label of the value (e. g. male or female) and is visible.
0
1
male
female
This way you can access both the value and the label of such a field. Notice the values of dataIndex and id on those columns. Those correspond with the output of "grid_data".
dataIndex
id
These examples imply that you use Catalyst as web framework and Template Toolkit as the templating engine.
Create a config file for the form (form.yml):
--- action: /contacts/create elements: - type: Text name: name label: Name constraints: - Required - type: Text name: address label: Address constraints: - Required - type: Button name: submit default: Submit attrs: handler: submitForm
In the last line there is a handler specified which is called when you press the submit button. This handler needs to be implemented using JavaScript.
Usually you have a JavaScript file which contains all the code you need for your page. To render the form you need to put the form definition in this file. Pass the form object to the stash so that you can access it from the template.
sub js : Local { my ($self, $c) = @_; my $form = new HTML::FormFu::ExtJS; $form->load_config_file('root/forms/form.yml'); $c->stash->{form} = $form; $c->stash->{template} = 'javascript.tt2'; } sub create : Path('/contacts/create') { my ($self, $c) = @_; my $form = new HTML::FormFu::ExtJS; $form->load_config_file('root/forms/form.yml'); $form->process($c->req->params); if($form->submitted_and_valid) { # insert into database } $c->stash($form->validation_response); # Make sure a JSON view is called so the stash is serialized }
javascript.tt2:
var submitForm = function() { form.getForm().submit({ success: function(rst, req) { // submission was successful and valid // you might want to close the form or something }, failure: function() { // form validation returned errors // invalid fields are masked automatically } } var form = [% form.render %];
See "simple form submission and validation" and "validation_response".
The FormFu constraints are not yet translated to ExtJS constraints. You can however add them manually in your form config:
- type: Text name: text constraint: - Required attrs: allowBlank: 0
If you wish to write your own ExtJS element you have to do the following:
First create an element which is a HTML::FormFu::Element.
package HTML::FormFu::Element::MyApp::MyField; use base qw(HTML::FormFu::Element::Text); 1;
This is a very basic example for a field which is a text field. The ExtJS logic belongs to a different module:
package HTML::FormFu::ExtJS::Element::MyApp::MyField; use base qw(HTML::FormFu::ExtJS::Element::Text); sub render { # you probably want to overwrite this! } 1;
Configure the form as follows:
$form->populate( { elements => { type => 'MyApp::MyField', ... } } );
If you don't want to put the element in the HTML::FormFu namespace then you have to prepend the class name with a +. In this case the name of the ExtJS class changes as well:
+
$form->populate( { elements => { type => '+MyApp::Element::MyField', ... } } );
This requires the classes MyApp::Element::MyField and MyApp::ExtJS::Element::MyField. The class must be in an Element namespace.
MyApp::Element::MyField
MyApp::ExtJS::Element::MyField
Element
The Multi element is rendered using the ExtJS column layout. It seems like this layout doesn't allow a label next to it. This module adds a new column as first element which has a field label specified and a hidden text box. I couldn't find a setup where this hack failed. But there might be some cases where it does.
Optgroups are partially supported. They render as a normal element of the select box and are therefore selectable.
Buttons cannot be placed in-line as ExtJS expects them to be in a different attribute. A button next to a text box is therefore (not yet) possible. Buttons are always rendered at the bottom of a form panel.
There is no support for comments yet. A work-around is to create a Multi element, add the element you want to comment in the first column and the comment as a Src element in the second column.
Each element in a Block element is rendered normally. The tag config option has no influence. If the Block element contains a content it is rendered like a Src element.
Block
tag
content
HTML::FormFu, JavaScript::Dumper
Moritz Onken <onken@netcubed.de>
This software is Copyright (c) 2011 by Moritz Onken.
This is free software, licensed under:
The (three-clause) BSD License
To install HTML::FormFu::ExtJS, copy and paste the appropriate command in to your terminal.
cpanm
cpanm HTML::FormFu::ExtJS
CPAN shell
perl -MCPAN -e shell install HTML::FormFu::ExtJS
For more information on module installation, please visit the detailed CPAN module installation guide.