Custom Form Helpers in Solar

Another thing that Solar makes easy is the creation of custom form helpers. These can be anything outside of the usual input types (like text, checkbox, textarea, etc) and can be used to make helpful, more complex inputs for your app.

In a previous post, I worked some with the Solar_Form class to create a login form. This just used simple input fields (text and password) to create the login form. I came to another part of my application where I needed a calendar helper to fill in some fields. I wanted to eliminate some of the user issues that could come with invalid dates being entered, so I opted to create a custom form field instead. The field is a normal text field, marked as READONLY with a link that launches a Javascript popup with the calendar picker.

First, we need a little structure – here’s how the application is structured (basically):

MyApp
 App
  Base
   Helper
    FormDate.php
   Layout
   Locale
   View
  Event
  Event.php
   Helper
   Layout
   Locale
   View
    index.php

There’s a few things involved here:

  • The form helper class – FormDate.php
  • The Event.php class (controller) where the form will be created
  • The View for the Event controller to output the form and some Javascript

We’ll start with building the form since that’s more familiar territory:

[php]
class MySite_App_Event extends MySite_App_Base {
protected $_action_default = ‘index’;
protected $_layout = ‘default’;
protected $_view =’index’;
public $forms;

public function actionIndex(){
$form = Solar::factory(‘Solar_Form’);
$form->setElements(array(
‘event_title’=>array(
‘type’=>’text’,
‘label’=>’Event Title’,
‘require’=>true,
‘valid’=>array(
array(‘notBlank’,’Please enter an event title!’)
)
),
‘event_start’=>array(
‘type’ =>’date’,
‘label’ =>’Start Date’,
‘require’=>true,
‘valid’ =>array(
array(‘notBlank’,’Please select a start date!’)
)
),
‘sub’=>array(
‘type’=>’submit’,
‘value’=>’create event’
)
));
$form->feedback=NULL;
$this->forms[‘create_form’]=$form;
}
}
[/php]

If you look close, you’ll spot something custom in there – on the event_start element, there’s a type of “date”. This how our special form helper is called. Solar does a little magic here – it looks at the types of each of the elements and looks in a few places for something that matches that type. Most of the elements are Solar’s default types so it falls back to the ones in the Solar directories. The “date” type, however, isn’t one of them and the app will break if you leave it like this.

So, what’s a developer to do? Well, create a custom form handler of course! This is where the FormDate.php file comes into play. Here’s what ours contains:

[php]
class MySite_App_Base_Helper_FormDate extends Solar_View_Helper_FormElement {

public function formDate($info){
$this->_prepare($info);
return ‘_view->escape($this->_name) . ‘”‘
. ‘ value=”‘ . $this->_view->escape($this->_value) . ‘”‘
. $this->_view->attribs($this->_attribs)
. ‘ READONLY/> _view->escape($this->_name).”)”>select‘;
}

}
[/php]

If you’ve been checking out the default Solar form fields, this should look familiar – it’s a ripoff of the default text field form helper that Solar comes with. The only addition is the Javascript-powered link there at the end that calls the date_picker application.

There’s a few things that need to be in place to get this to work. First off, the class name needs to be the right “path” to the file. So, for our class it corresponds to MySite/App/Base/Helper to tell Solar where the file exists. If this isn’t right, Solar won’t be able to find and use the file. Next thing to look out for is the last part of the class name – FormDate for us. The second part of this is what Solar uses when the class is called. So, for example, we use FormDate because we want the type to be “date”. If we wanted one that was some kind of special field that works with Google’s Maps, we could use FormGoogle and define our custom form field inside it. Speaking of inside, the method’s name has to match the class name – FormDate and formDate – and takes in the information passed to it (including the field name, the value to fill it with and attributes it might have).

Because this file exists in the Base controller’s Helper directory and our Event class extends the Base, we can use it. Plus, by putting it up in the Base Helper directory, we can use it in other places in the site that extend Base.

Now we’ll move on to the last part of the equation – the View for the Event controller:

[php]

function date_picker(fname){
elem=document.getElementById(fname);
elem.value=’08/14/1977′;
}

form($this->forms[‘create_form’]);
?>
[/php]

In the View above (our index.php file), we define the Javascript function our custom helper will use – date_picker – that takes in the element name. In a real application, this would be the place to interface with another page (or maybe even some sort of Ajax request) to let the user pick the date. As it stands, though, we’re just putting our predefined date in the field. The PHP part is simple, just an execution of the form.

Ideally, you’d put any and all Javascript in a few files out in the public directory of your application rather than in the view itself, but since we’re going for simplicity here I’ve just put it in the page itself.

So, there we go – a simple method to make a custom form handler that you can use anywhere in your application. It’s pretty easy to see how you can expand upon this to make just about any kind of custom form element that you might want…

2 comments

  1. just a note: adding the javascript could be automatized using $this->_view->js()->addInlineScript() inside the FormDate helper. then, when calling the helper, the necessary inline javascript script would be added to the page head. solar beauty! 🙂

    Like

  2. This Solar thing seems pretty nice. At least the form features, doesn’t seem to have that many other built-in things. There’s just one thing, though. It doesn’t look like you have much to say on how the form will end up looking like markup-wise. I think I would prefer something that perhaps generates the input elements, but would let me pick where to put them. Something like $this->forms[‘create_form’]->inputs[‘foobar’]

    What would be really cool would be a class that could build a form, a parser and JS validators based on a DB table or a row. Well, it might need some assistance, since the table column names wouldn’t probably be very good labels on the form… so perhaps it isn’t very feasible afterall.

    Like

Leave a comment