Create A Form
Create a new form instance and add fields into it.
use Windwalker\Form\Field\TextareaField;
use Windwalker\Form\Form;
use Windwalker\Form\Field\TextField;
use Windwalker\Form\Field\PasswordField;
$form = new Form;
$form->addField(new TextField('username', 'Username'));
$form->addField(new PasswordField('password', 'Password'));
// Another way
$form->add('email', new TextField)->label('Email');
$form->add('description', new TextareaField)->label('Description'));
echo $form->renderFields();
Render all fields, and we get this HTML output.
<div id="username-control" class="text-field ">
<label id="username-label" for="username">Username</label>
<input type="text" name="username" id="username" />
</div>
<div id="password-control" class="password-field ">
<label id="password-label" for="password">Password</label>
<input type="password" name="password" id="password" />
</div>
<div id="email-control" class="text-field ">
<label id="email-label" for="email">Email</label>
<input type="text" name="email" id="email" />
</div>
<div id="description-control" class="textarea-field ">
<label id="description-label" for="description">Description</label>
<textarea name="description" id="description"></textarea>
</div>
Using XML as Configuration
<form>
<field
name="username"
type="text"
label="Username"
/>
<field
name="password"
type="password"
label="Password"
/>
</form>
$form = new Form;
$form->loadFile('form.xml');
Field Definition Interface
FieldDefinitionInterface
is a simple interface to help us create an empty space to define form fields.
use Windwalker\Form\FieldDefinitionInterface;
class MyFieldDefinition implements FieldDefinitionInterface
{
public function define(Form $form)
{
$form->add('name', new TextField)->label('Name');
}
}
Then add this definition to Form object.
$form = new Form;
$form->defineFormField(new MyFieldDefinition);
Form Control
$control = 'user';
$form = new Form($control);
$form->addField(new TextField('username', 'Username'));
echo $form->renderFields();
The result will make name as an array.
<div id="user-username-control" class="text-field ">
<label id="user-username-label" for="user-username">Username</label>
<input type="text" name="user[username]" id="user-username" />
</div>
Organize Fields
Fieldset
Fieldset is a category of fields, we can filter our fields by fieldset:
$form = new Form;
$form->addField(new TextField('flower', 'Flower'), 'plant');
$form->addField(new TextField('tree', 'Tree'), 'plant');
$form->addField(new TextField('dog', 'Dog'), 'animal');
$form->addField(new TextField('cat', 'Cat'), 'animal');
// Only render Flower & Tree
echo $form->renderFields('plant');
// Only render Dog & Cat
echo $form->renderFields('animal');
// Will render all
echo $form->renderFields();
Using XML
<form>
<fieldset name="plant">
<field name="flower" label="Flower"/>
<field name="tree" label="Tree"/>
</fieldset>
<fieldset name="animal">
<field name="dog" label="Dog"/>
<field name="cat" label="Cat"/>
</fieldset>
</form>
Group
Group is like fieldset as a category of fields, but it will make name of fields to be array:
$form = new Form;
$form->addField(new TextField('flower', 'Flower'), null, 'earth');
$form->addField(new TextField('bird', 'Bird'), null, 'sky');
// The name will be name="earth[flower]"
echo $form->renderFields(null, 'plant');
// The name will be name="sky[bird]"
echo $form->renderFields(null, 'animal');
<input type="text" name="earth[flower]" />
<input type="text" name="sky[bird]" />
Now we can use fieldset and group to organize our fields.
$form = new Form;
$form->addField(new TextField('flower', 'Flower'), 'plant', 'earth');
$form->addField(new TextField('tree', 'Tree'), 'plant', 'earth');
$form->addField(new TextField('dog', 'Dog'), 'animal', 'home');
$form->addField(new TextField('cat', 'Cat'), 'animal', 'home');
$form->addField(new TextField('bird', 'Bird'), 'animal', 'sky');
// Only render Bird
echo $form->renderFields('animal', 'sky');
// Only render Dog & Cat & Bird
echo $form->renderFields('animal');
// Only render Flower & Tree
echo $form->renderFields(null, 'earth');
// Will render all
echo $form->renderFields();
Using XML
<form>
<group name="earth">
<fieldset name="plant">
<field name="flower" label="Flower"/>
<field name="tree" label="Tree"/>
</fieldset>
</group>
<fieldset name="animal">
<group name="home">
<field name="dog" label="Dog"/>
<field name="cat" label="Cat"/>
</group>
<group name="home">
<field name="bird" label="Bird"/>
</group>
</fieldset>
</form>
Use Wrapper Methods
Windwalker 2.1 supports wrapper method to help us organize form fieldset and group.
$form->wrap('fieldset', null, function(Form $form)
{
$form->add('name', new TextField)
->label('Name')
->required();
$form->add('email', new TextField)
->label('Email')
->required();
$form->add('password', new PasswordField)
->label('Password')
->set('autocomplete', 'off');
$form->add('password2', new PasswordField)
->label('Confirm Password')
->set('autocomplete', 'off');
});
// Use group
use Windwalker\Html\Option;
$form->wrap('fieldset', 'group', function(Form $form)
{
// State
$form->add('state', new Field\RadioField)
->label('State')
->set('class', 'btn-group')
->set('default', 1)
->addOption(new Option('On', '1'))
->addOption(new Option('Off', '0'));
});
Attributes of Fields
Name & Label
$form->addField(new TextField('name', 'Label'));
Set Attributes
$form->addField(new TextField('name', 'Label'))
->set('id', 'my-name')
->set('class', 'col-md-8 form-input')
->set('onclick', 'return false;');
Required, Disabled and Readonly
$form->addField(new TextField('name', 'Label'))
->set('id', 'my-name')
->required()
->disabled();
Set to false.
$form->addField(new TextField('name', 'Label'))
->set('id', 'my-name')
->required(false)
->disabled(false);
XML
<field
name="name"
label="Label"
id="my-name"
required="true"
disabled="false"
/>
Filter
use Windwalker\Filter\InputFilter;
$form->addField(new TextField('id', 'ID'))
->setFilter(InputFilter::INTEGER);
// Prepare data
$data['id'] = '123abc';
// Bind data into form
$form->bind($data);
// Do filter
$form->filter();
$values = $form->getValues(); // Array(id = 123)
Validate
$form->addField(new TextField('name', 'Name'))
->required();
$form->addField(new TextField('email', 'Email'))
->setValidator(new EmailValidator);
// Prepare data
$data['name'] = null;
$data['email'] = 'foo';
// Bind data into form
$form->bind($data);
// Do validate
$r = $form->validate();
$results = $form->getErrors();
var_dump($r); // bool(false)
$results[0]->getMessage(); // Field Email validate fail.
$results[1]->getMessage(); // Field Name value not allow empty.
Field Types
Select List
use Windwalker\Form\Field\ListField;
use Windwalker\Html\Option;
$selectField = new ListField(
'flower',
'Flower',
array(
new Option('', ''),
new Option('Yes', 1),
new Option('No', 0),
)
);
echo $selectField->render();
The output is:
<div id="flower-control" class="list-field ">
<label id="flower-label" for="flower">Flower</label>
<select name="flower" id="flower" class="stub-flower">
<option selected="selected"></option>
<option value="1">Yes</option>
<option value="0">No</option>
</select>
</div>
Multiple List
$selectField->set('multiple', true);
RadioList
$form->addField(new RadioList('flower', 'Flower'))
->addOption(new Option('Yes', 1))
->addOption(new Option('No', 0));
We can also add options in constructor:
$field = new RadioList(
'flower',
'Flower',
array(
new Option('Yes', 1),
new Option('No', 0),
)
);
Available Fields
Name | HTML | Description |
---|---|---|
TextField | <input type="text"> |
The text input field. |
TextareaField | <textarea></textarea> |
Textarea field. |
EmailField | <input type="email"> |
The email text field. |
HiddenField | <input type="hidden"> |
Hidden input. |
PasswordField | <input type="password"> |
Password field. |
SpacerField | <hr> |
The spacer to separate fields and fields. |
ListField | <select> |
Select list. |
CheckboxField | <input type="checkbox"> |
Single checkbox. |
CheckboxesField | <input type="checkbox"> |
Checkbox list. |
RadioField | <input type="radio"> |
Radio list. |
TimezoneField | <select> |
A timezone select list. |
Custom Fields
Custom TextField.
namespace MyCode\Fields;
class FooField extends TextField
{
protected $type = 'foo';
public function prepare(&$attrs)
{
parent::prepare($attrs);
$attrs['bar'] = $this->getAttribute('bar');
}
}
For XML
\Windwalker\Form\FieldHelper::addNamespace('MyCode\Filter');
<field
name="foo"
type="foo"
/>
Custom List field
namespace MyCode\Fields;
class UsersField extends ListField
{
protected function prepareOptions()
{
$users = Database::getList('SELECT * FROM users');
$options = array();
foreach ($users as $user)
{
$options[] = new Option($user->name, $user->id);
}
return $options;
}
}
Custom Filter
namespace MyCode\Filter;
class MyFilter implements FilterInterface
{
public function clean($text)
{
return my_filter_function($text);
}
}
(new TextField('foo', 'Foo'))
->setFilter(new MyFilter);
For XML
\Windwalker\Form\FilterHelper::addNamespace('MyCode\Filter');
<field
name="foo"
type="text"
filter="my"
/>
Custom Validator
namespace MyCode\Validator;
use Windwalker\Validator\AbstractValidator;
class MyValidator extends AbstractValidator
{
protected function test($value)
{
return (bool) $value;
}
}
(new TextField('foo', 'Foo'))
->setFilter(new MyValidator);
For XML
\Windwalker\Form\ValidatorHelper::addNamespace('MyCode\Validator');
<field
name="foo"
type="text"
filter="my"
/>
Renderer
We can add our own custom renderer to render form fields. This is a renderer example.
class MyFormRenderer
{
public static function render(AbstractField $field, Form $form)
{
switch($field->getType())
{
case 'text':
return static::renderText($field, $form);
break;
case 'list':
case 'radio':
case 'checkboxes':
return static::renderList($field, $form);
break;
// More...
default:
return static::renderInput($field, $form);
}
}
// more ...
}
Add renderer callback to Form:
$form->setFieldRenderHandler(array('MyFormRenderer', 'render'));
Or use invokable object.
class MyFormRenderer
{
public function __invoke(AbstractField $field, Form $form)
{
// ...
}
// more ...
}
$form->setFieldRenderHandler(new MyFormRenderer);
If you found a typo or error, please help us improve this document.