Jump to content

Community

Developer Documentation

Overview of the IPS4 Form Helpers

Purpose of the Form Helper

Much of the UI in IPS4 revolves around forms, whether it's the numerous settings screens in the AdminCP, replying to content on the front end, configuring your profile, and so on.

The IPS Community Suite has a powerful Form Helper class that simplifies implementing forms in your applications and plugins. It provides features such as automatic validation and built-in security, and (in the case of more complex field types such as matrices and node/tree selectors) takes care of generating the UI and dynamic behavior for you. Forms created with the Form Helper support a wide range of field types, have built-in tab support, use HTML5 features where applicable, and more.

If you require input from users in your application or plugin, you should always use the Form Helper; never implement such functionality manually and bypass the framework.

Here's a basic stub showing how your form code will eventually look:

// Create the form instance
$form = new \IPS\Helpers\Form;

// Add our form fields
$form->add( ... );
$form->add( ... );

if ( $values = $form->values() )
{
	// Form submitted; handle the form values here
}

// Send the form for output
\IPS\Output::i()->output = $form;

 

Creating a form

To create a form, you simply create an instance from the Form Helper. To the returned object you can add fields, tabs, and more (see the following sections).

// Create a form using defaults
$form = new \IPS\Helpers\Form;

No parameters are required, but there's a few optional parameters you can pass:

\IPS\Helpers\Form( [ string $formID='form' [, string $submitLang='save' [, \IPS\Http\Url $actionURL=NULL [, array $attributes=array() ]]]] );

 

  • $formID (string, optional)
    The ID to use in the HTML id attribute for this form
  • $submitLang (string, optional)
    The language key of the string to use in the primary 'submit' button for this form
  • $actionURL (\IPS\Http\Url, optional)
    A URL object representing the URL the form should post to (by default, forms post to the same page that displays them, for easy processing)
  • $attributes (array, optional)
    An array of key/values of other HTML attributes you might want to include in the <form> tag, such as for javascript functionality.

 

Adding form elements

Adding an element a form is done by the $form->add() method. You pass it an object of the element you want - for example, to add a text input to your form, you can do:

$form->add( new \IPS\Helpers\Form\Text('name') );

There's a wide range of built-in form field types for you to use. Some of the classes available are:

  • \IPS\Helpers\Form\Text for normal text input
  • \IPS\Helpers\Form\Editor for WYSIWG text input
  • \IPS\Helpers\Form\Upload for file uploads
  • \IPS\Helpers\Form\Date for dates
  • \IPS\Helpers\Form\Select for a select box
  • \IPS\Helpers\Form\YesNo for yes/no radio buttons

All form field classes have the same parameter signature. Each is customized by the values you pass in. Here are the parameters you can pass to form field classes:

__construct( string $name [, mixed $defaultValue=NULL [, boolean $required=FALSE [, array $options=array() [, function $customValidationCode=NULL [, string $prefix=NULL [, string $suffix=NULL [, string $id=NULL ]]]]]]] );

 

  • $name (string, required)
    The field name (used in the HTML name attribute.
  • $defaultValue (mixed, optional)
    The default value of the field, in whatever is the appropriate type for this field
  • $required (boolean, optional)
    Is this field required? Note: passing true sets the HTML5 required attribute, meaning the form can't be submitted unless this is filled. Passing NULL instead disables the HTML5 required attribute, allowing you to validate it manually on the backend instead.
  • $options (array, optional)
    An array of options. The acceptable values vary depending on the field type; consult the individual classes for more information.
  • $customValidationCode (function, optional)
    A closure that validates the value of the field
  • $prefix (string, optional)
    HTML string to show before the field HTML
  • $suffix (string, optional)
    HTML string to show after the field HTML
  • $id (string, optional)
    The ID to be used in the HTML id attribute

For all of the available classes, look at the files in the system/Helpers/Form/ directory. The values acceptable for $options are documented in the source code for each. Be aware that some extend others (for example CheckboxSet extends Select, and has the same $options).

For example, to create a multi-select box you would do something like:

$form->add( new \IPS\Helpers\Form\Select( 'my_select_box', NULL, TRUE, array( 'options' => array( 0 => 'Foo', 1 => 'Bar', 2=> 'Baz' ), 'multiple' => TRUE ) ) );

 

Labels and Descriptions

The $name property, in addition to being the name used for the HTML field, is also used for the label to display. The form helper will automatically look for a language string with the same key to use as the label.

It will also look for a language string appended with _desc for the description. For example, if the $name for your field is my_field, it will use the language string my_field_desc as the description. If a language string with that key doesn't exist, no description will be used.

It will also look for a language string appended with _warning for a warning block (again if it doesn't exist none is shown). This is normally only ever used with toggles (see below) for example to display a warning when the user selects a particularly dangerous option.

In addition to labels and descriptions using language string's automatically, it is also possible to override this behaviour and set your own values in the controller. For example:

$input = new \IPS\Helpers\Form\Text( 'my_select_box', NULL, TRUE );
$input->description = "My Description";
$input->label = "My Label";

It is important to note that when setting descriptions in this way they will be added to the for exactly as provided with no additional markup. If markup is required then you should set the property using a template.
 

Validation

Most classes will provide automatic validation, and their $options provide ways of customizing this. For example, if you create an \IPS\Helpers\Form\Number element, it will automatically check if the value is a number, and you can use $options to control the maximum and minimum along with the number of allowed decimal points. The system will automatically display the form again with an inline error message if any of the elements don't validate with no extra code required from you. If however, you want to include custom validation, you can do this with the $customValidationCode property - you simply provide a callback method which throws a DomainException if there's an error. For example, if you wanted a number field where the number 7 is specifically not allowed you could do this like so:

$form->add( new \IPS\Helpers\Form\Number( 'my_field', NULL, TRUE, array(), function( $val )
{
	if ( $val == 7 )
	{
		throw new \DomainException('form_bad_value');
	}
} ) );

 

Handling submissions

When your form is submitted, $form->values() will return an array with the values of each element (if the form has not been submitted or validation fails, it returns FALSE). Be aware that CSRF protection is handled automatically when you use the centralized \IPS\Helpers\Form class and an error message will be shown if the CSRF key does not match the expected value.

The value returned for each element depends on the type, and sometimes the options. For example, an \IPS\Helpers\Form\Text element always returns a string as it's value. However, \IPS\Helpers\Form\Number might return an integer or a float. \IPS\Helpers\Form\Upload, on the other hand, returns an \IPS\File object (or even an array of them if it's a multiple file upload field).

If you prefer to only receive string values (for example, you want to save the values as a JSON object), you can pass TRUE to the $form->values() method.

 

Advice and best practices

Forms make up a large portion of the UI within the IPS Community. It is important to remember to present a UI that is consistent with other areas of the suite. To this end, we recommend the following best practices:

  • Always phrase settings in the positive. For example, say "Enable feature?", don't say "Disable feature?". "Yes" should always mean something is "On".
  • Make labels short and concise and use descriptions only if necessary. For example, don't have a field where the label is "Enable feature?" and the description is "Set this to yes to enable the feature" - that description isn't necessary.
  • Use prefixes and suffixes rather than adding information to the label or description where possible. For example, don't have a label that says "Number of days before deleting" - make the label "Delete after" and the suffix that appears after the field say "days".
  • Never refer to other settings in labels or descriptions. For example, do not have a description that says "Only applies if the above setting is on". Use toggles to indicate this to the user.
  • Never make entering a particular value do something special. For example, do not have a description that says "Leave blank for unlimited" - use an unlimited checkbox or a separate setting which toggles other settings.

  Report Document


×
×
  • Create New...