Improve this Doc

Form Core

class Form

Implement HTML form

Form::addField($class, $options, $caption)

add form field

A most fundamendal form would have a few fields defined, submit button and handler.

When adding a field, you must remember that Form_Field is very different from Model Field.

addField can be called in various ways:

$form->addField('title');
$form->addField('Line', 'title');
$form->addField('Line', ['name'=>'title']);
$form->addField('Line', ['name'=>'title'], 'Title');

Although any of the lines above will produce exactly same result.

The form template has an area for buttons. When you use addSubmit() it adds the button in this area. addSubmit will also highlight the button so it would appear visually distinctive from other buttons. addSubmit also assigns icon to the button. You can override this through Component Definition Array.

When adding a field, method will return instance of Form_Field. Chaining additional calls can help you change the way how the field is working:

$form->addField('title')->validateNotNull();

As mentioned before, form will submit itself through AJAX. You can switch this off with js_widget property:

property Form::$js_widget

Name of jQuery UI Widget to enhance form into AJAX submission. Setting this property to null or false will disable the property.

When disabled, form will automatically read and populate POST data into it’s fields.

The other way how you can get some data into a form is using set() method.

Form::set($field, $value)

This will call Form_Field::set ($value) to set default value of the field. Call this before handling submission.

Adding Buttons

Form supports two types of buttons: submit and regular buttons.

Submit buttons will take all the form data and send it back with POST. Regular Buttons are just that - regular Button

Form::addSubmit($label)

Create a submission button.

Form::addButton($label)

Create a regular button.

Submission handling

Adding buttons is not enough. You also need to capture submission event. Form routes submission request to exactly same page with exactly same GET data (See Sticky GET), however you can tell the request apart by with the following two methods:

Form::isSubmitted()

returns true if form is being submitted.

Form::onSubmit($callback)

executes callback if form is being submitted passing form itself as first argument.

If you have created multiple submission buttons you can use isClicked method to verify which one was clicked.

Form::isClicked($submit_button)

When you have multiple submission button, you can call isClicked on any button to verify if it has been clicked.

Note

If user has pressed enter in the form isClicked will always return false.

Next example implements dual submit of a form. If the Save and Add New is clicked, then after saving, user stays on the same page possibly adding more records. Just clicking Save button will return user to the parent page (See URL and Universal JS Chain for more info on redirects and routes):

$form->addSubmit('Save');
$save_and_add = $form->addSubmit('Save and Add New');

$form->onSubmit(function($form) use ($save_and_add) {

    $form->save();

    if ($form->isClicked($save_and_add)) {
        return $form->js()->univ()->redirect($form->app->url());
    }

    return $form->js()->univ->redirect($this->app->url('..'));
});

Responding on submission with errors

If instead of successful submission you want to display an error, form allows you to do that

Form::error($field, $message)

Displays error message under $field.

Example:

$form->onSubmit(function($form) {
    if($form['age']<10) return $form->error('age','too young');

    $form->save();
    return 'Success';
});

Form also respects in-model validation and will display error message next to an appropriate field. See Exception_ValidityCheck and Validator.

Associating with Model

Most commonly you will use Form to edit Model data. For that you should use:

Form::setModel($model, $actual_fields)

Associate form with model and populate actual fields. Form::update will save this model.

You can associate form with more models by calling

Form::importFields($model, $fields)

Add fields from model into form. Also Form::update will save this model.

Example using Form with one model:

$form = $this->add('Form');
$form->setModel('Book', ['title','descr']);

If you want form to edit multiple models, you can import fields. Note that the model for Import Fields must be alerady initialized:

$author = $form->model->ref('author_id');
$form->importFields($author, ['name', 'surname']);
Form::save()

Copy submitted field data into associated models and call Model::save.

Form can automatically save fields into model record:

$form->onSubmit(function($f){
    $f->save();
    return 'Saved Successfully';
});

If your model was Model::loaded with particular record, then this record will save back modified fields. Otherwise a new record is created.

Advanced use with models

You can associate Form with a model, but do not import any fields initially:

$form->setModel('Book', false);

This actually initializes a special controller: Controller_MVCForm, which is responsible for binding Form with Model and also transitioning Model field types into Form Field types.

You can access this controler to call Controller_MVCForm::importField:

$form->controller->importfield('title');

This will create field in form with the identical name (if possible). You can then access Form_Field as a regular child of a form:

$form->getElement('title');

Please note that if you want to access Form Field, you can use:

$form->model->getElement('title');