NAME
Valiant::HTML::Form - HTML Form
SYNOPSIS
Given a model like:
package Local::Person;
use Moo;
use Valiant::Validations;
has first_name => (is=>'ro');
has last_name => (is=>'ro');
validates ['first_name', 'last_name'] => (
length => {
maximum => 20,
minimum => 3,
}
);
Wrap a formbuilder object around it and generate HTML form field controls:
use Valiant::HTML::Form 'form_for';
my $person = Local::Person->new(first_name=>'J', last_name=>'Napiorkowski');
$person->validate;
form_for($person, sub($fb, $person) {
return $fb->label('first_name'),
$fb->input('first_name'),
$fb->errors_for('first_name', +{ class=>'invalid-feedback' }),
$fb->label('last_name'),
$fb->input('last_name'),
$fb->errors_for('last_name'+{ class=>'invalid-feedback' });
});
Generates something like:
<form accept-charset="UTF-8" id="new_person" method="post">
<label for="person_first_name">First Name</label>
<input id="person_first_name" name="person.first_name" type="text" value="John"/>
<div class='invalid-feedback'>First Name is too short (minimum is 3 characters).</div>
<label for="person_last_name">Last Name</label>
<input id="person_last_name" name="person.last_name" type="text" value="Napiorkowski"/>
</form>
DESCRIPTION
Export helper methods to properly create instances of Valiant::HTML::FormBuilder that will also wrap the builder in proper form
tags.
Its possible other methods will move here from Valiant::HTML::FormBuilder to make it easier for people to build form tags without needed to create a full on builder. Please make you requests and demonstrated use cases in a ticket.
REQUIRED MODEL API
This (and Valiant::HTML::FormBuilder) wrap an object model that is expected to do the following interface.
to_model
This is an optional method. If this is supported, we call to_model
on the wrapped object before using it on the form methods. This allows you to delegate the required API to a secondard object, which can result in a cleaner API depending on your designs and use cases.
in_storage
This is an optional method. If your object has a backing storage solution (such as your object is an instance of a DBIC Result Source) you can provide this method to influence how your object form tags are created. If provided this method should return a boolean when if true means that the object is representing data which is stored in the backing storage solution. Please note that this does not mean that the object is synchronized with the backing storage since its possible that the object has been changed by the user.
is_attribute_changed
$model->is_attribute_changed($attr); # true or false
Optional method. If provided returns a boolean if the attribute has been changed from its initial state, as defined by either being different from the backing store (if it exists) or being changed from its default value when created as a new model.
human_attribute_name
$model->human_attribute_name('user'); # User
Optional. If provided, uses the model to look up a displayable version of the attribute name, for example used in a label for an input control. If not present we use Valiant::HTML::FormTags\_humanize to create a displayable name from the attribute name.
read_attribute_for_html
$model->read_attribute_for_html('user'); # User
Optional. If provided must access the string name of the field or attribute and should return the model value for that attribute suitable for HTML form display. You might wish to use this as a way to deflate or otherwise stringify non string values. If not provided we just use the attribute name and call it as an accessor against the model.
errors
Optional. Should return an instances of Valiant::Errors. If present will be used to lookup model and attribute errors.
Please note this currently is tried to behavior expected from Valiant::Errors but in the future we might try to make this tied to a defined interface rather than this concrete class.
has_errors
Optional if you don't use builder methods that are for displaying errors; required otherwise. A boolean that indicates if your model has errors or not. Used to determined if error_classes
are merged into class
and in a few similar places.
i18n
Optional. If provided should return an instance of Valiant::I18N. Used in a few places to support translation tags.
model_name
Optional. If provide should return an instance of Valiant::Name. Used in a few places where we default a value to a human readable version of the model name. If you don't have this method we fall back to guessing something based on the string name of the model.
primary_columns
Optional. When a model does in_storage
and its a nested model, when this method exists we use it to get a list of primary columns for the underlying storage and then add them as hidden fields. This is needed particularly with one - many style relationships so that we find the right record in the storage model to update.
NOTE: This method requirement is subject to change. It feels a bit too tightly bound to the idea of and ORM and to DBIx::Class in particular.
is_marked_for_deletion
Optional, but should be supported if your model supports a storage backend. A boolean that indicates if the model is currently marked for deletion upon successful validation. Used for things like radio and checkbox collections when the state should be 'unchecked' even if the model is still in storage.
EXPORTABLE FUNCTIONS
The following functions can be exported by this library
form_for
form_for($person, sub($fb, $person) {
$fb->input('name');
$fb->label('name');
});
# Generates something like:
<form accept-charset="UTF-8" id="new_person" method="post">
<label for="person_name">Name</label>
<input id="person_name" name="person.name" type="text" value="John"/>
</form>
Given a model as described above, wrap a Valiant::HTML::FormBuilder instance around it which provides methods for generating valid HTML form output. This provides a view logic centered method for creating sensible and reusable form controls which include server generated error output from validation.
See Valiant::HTML::FormBuilder for more on the formbuilder API.
\%options
are used to influence the builder creation as well as pass attributes to the generated form
tag. Options are as follows:
- as
-
Supplies the
name
argument for Valiant::HTML::FormBuilder. This is generally used to set the top namespace for your field IDs andname
attributes. - method
-
Sets the form attribute
method
. Generally defaults topost
orpatch
(whenin_storage
is supported and the model is marked for updating of an existing model). - action
-
Should be the URL that the form with post to.
- data
-
a hashref of HTML tag <data> attributes.
- class
- style
-
HTML attributes that get merged into the
html
options (below) - html
-
a hashref of items that will get rendered as HTML attributes for the form.
- namespace
-
Optional. Can use used to prepend a namespace to your form IDs
- index
-
Optional. When processing a collection model this will be the index of the current model.
- builder
-
The form builder. Defaults to Valiant::HTML::FormBuilder. You can set this if you create your own formbuilder subclass and want to use that.
The last argument should be a reference to a subroute that will receive the created formbuilder object and should return a string, or array of strings that will be flattened and displayed as your form elements. Any strings returns not marked as safe
via Valiant::HTML::SafeString will be encoded and turned safe so be sure to mark any raw strings correctly unless you want double encoding issues.
fields_for
fields_for($sub_model_name, $model, $options, sub($fb, $model) {
$fb->input($field);
});
Create an instance of a formbuilder that represents a sub model (that is a model with is associated with a parent model under an attribute of that parent.
Unless you are doing very customized form generation you'll probably use this as a method of a formbuilder such as Valiant::HTML::FormBuilder. However there was no reason for me to not expose the method publically for users who need it.
The second argument for the callback subroutine reference is the current model. If the passed model is a collection this will always be the current one.
SEE ALSO
Valiant, Valiant::HTML::FormBuilder
AUTHOR
See Valiant
COPYRIGHT & LICENSE
See Valiant