Jump to content

4.0 - Forms

Forms are an ubiquitous aspect of any web application. In the IPS Social Suite, particularly in the Admin CP, I often find myself copying and pasting code in various places to create a form. We've had the ipsRegistry::getClass('output')->formInput() and similar methods since 3.0, but you still have to copy all the HTML to display the rows, and write all the code to validate it yourself.

Copying and pasting code is something all developers hate. It's a red flag that you're probably doing something wrong. In IPS 4.0, we've written a central form building helper class to alleviate this.

Just as a reminder: Everything in this blog is a work in progress - naturally someone with a much keener design sense than I will be going over the interface - I'm just demonstrating the functionality, not a finished product :smile:

The Basics

Let's say I want to create a form with a single text input field. I simply initiate the form, add an object representing the input, and then display the form (it has a __toString method) - like so:

$form = new IPSHelpersForm();
$form->add( new IPSHelpersFormText( 'name', 'default value' ) );
IPSOutput::i()->output .= $form;

The helper will automatically look for language strings with the same name as the form element and use them. If there is a language string with the same name and then "_desc" - it'll use that as the description.

So the above code, in the ACP, produces something like this:


Let's say I want the field to be required - I just pass a third argument indicating so. When the form is submitted, if no value has been provided, it will automatically display an inline error:

new IPSHelpersFormText( 'name', '', TRUE )


The fourth argument I can pass is an array with options dependent on the type of input field I'm adding. These options may change the way a field is displayed or add additional validation.

So for a text field, I can specify the minimum and maximum length (which, naturally takes multibyte languages into consideration):

new IPSHelpersFormText( 'name', '', TRUE, array( 'minLength' => 5 ) )

For a number field, I might specify the number of decimal points to round to, which it will do on the fly:

new IPSHelpersFormNumber( 'name', 0, TRUE, array( 'decimals' => 2 ) )

Watch Video

Or I could add an "Unlimited" checkbox, which is quite common for Admin CP settings:

new IPSHelpersFormNumber( 'name', 0, TRUE, array( 'unlimited' => TRUE ) )

Custom Validation

If the built-in options don't provide enough validation for a given need, you can pass a lambda function as a 5th argument:

new IPSHelpersFormText( 'name', '', TRUE, array(), function( $val )
	if ( $val === 'Bad Value' )
		throw new IPSHelpersFormException( 'That value is not allowed.' );
} )


Of course - simple input fields aren't all that can be done. How does drag and drop uploading sound?

new IPSHelpersFormUpload( 'name', NULL, FALSE, array( 'multiple' => TRUE ) )

Watch Video

(By the way, you'll notice a stripy bar flashes up briefly - this is a real progress bar, but because I'm uploading to localhost it's filling faster than it displays - in practice, you'll see a nice smooth-filling progress bar)

Getting the values

The form helper will by default (you can override it of course) submit to the same page it's on. You can check if it has been submitted (and passed validation) and obtain the values if so simply by calling the values() method - here's an example:

$form = new IPSHelpersForm();

$form->add( ... );

if ( $values = $form->values() )
	// $values contains the values from the form
	IPSOutput::i()->output .= $form;

The values will be returned in a way that is appropriate to the input type. For example, a text input field will return a string, number input will return either an integer or float, an upload field will return an IPSFile object (or array of them, if you're accepting multiple files), etc.

  • Create New...