<code><form id="TaskEditForm" method="post" action="">" onSubmit="return false;"></code>
</p><p>Here we see a hand-coded form tag with embedded PHP, echoing the ID of the current Task object. Now consider the following code, updated for 1.2, which produces effectively the same output:</p> (New)
<code><?=$form->create(array('default' => false)); ?></code>
<p>Okay, let's start with what we don't see. You'll notice first that we don't see any reference to a URL; neither a controller nor an action; not even a model name. We also don't see a DOM ID, or any reference to the JavaScript event in the preceeding code. Let's start with the bit about the model. In Cake 1.2, we're transitioning to an approach to form building that is more directly model-oriented, and according to the API, the first parameter to <code>FormHelper::create()</code> is actually supposed to be the name of a model, i.e.:</p> <code><?=$form->create('Task', array('default' => false)); ?></code>
<p>However, if you don't provide one, it is assumed to be the default model for the controller (in this case TasksController).</p> <p>So how does it even know whether this is an add or edit form? Simple: it checks <code>$this->data</code> for a value for the primary key for the given model. If it is set and not empty, it is assumed to be an edit form, otherwise it is an add form. According to convention, 'add' and 'edit' are the default names for form-related actions. Most of the rest of the attributes are pretty straightforward: as with form elements, DOM IDs are now auto-generated for forms themselves, based on the model and type (add/edit).</p> <p>The last remaining bit is <code>'default' => false</code>. This is new for both forms and links, and provides you a simple way to disable the default action without actually having to write any JavaScript.</p> <p>We've also replaced most of the form-related methods in HtmlHelper with roughly equivalent ones in FormHelper. We've also added some wrapper methods to FormHelper, which you can provide with a few hints about how you want your form elements to render, and they take care of everything for you. Here's an example:</p> (Old)
<pre><code>
// Controller:
$this->set('contacts', $this->Task->Contact->generateList());
// View:
<div class="input">
<label for="TaskContactId">Assigned to</label>
<?=$html->selectTag('Task/contact_id', $contacts, $this->data['Task']['contact_id'], null, null, false); ?>
</div>
</code></pre> (New)
<pre><code>
// Controller:
$this->set('contacts', $this->Task->Contact->generateList());
// View:
<?=$form->input('contact_id', array('label' => 'Assigned to', 'empty' => false)); ?>
</code></pre> <p>Again, both code listings produce effectively the same output.</p> <p><code>FormHelper::input()</code> takes various hints about what type of form element you want it to generate based not only on the information you provide it, but also on the field's model data, and on the view environment itself. Let's first compare the <code>$form->input()</code> part with the <code>$html->selectTag()</code> (you can ignore the controller code, it's the same in both). The first thing is the lack of the 'Task/' part in the field definition that is passed to the method. We're still using that syntax, but if you don't provide a model name, that's okay, because Cake already knows that we're creating a form for the Task model, so it is used automatically.</p> <p>The next thing you'll notice is that <code>$contacts</code>, our list of options to actually use in the <select> element, is not present in the view code at all. Since Cake knows that contact_id is a foreign key to another model, it checks the view for a variable called <code>$contacts</code> (the plural of the key name, with the '_id' part removed), and if it is found (and it is an array), Cake uses it as the option list.</p> <p>The other factors that determine the type of form field that <code>input()</code> will generate are as follows: </p><ul><li>As in the above example, if the field is a foreign key, and the corresponding options variable is specified, a select menu will be rendered.</li><li>If you specify an <code>'options'</code> key in the second parameter, a select menu will be rendered.</li><li>If the field name is <code>'password'</code> or <code>'passwd'</code>, a password field will be rendered.</li><li>Text and varchar fields are rendered as textareas and text inputs, respectively.</li><li>Booleans render as checkboxes (and the label is rendered to the <em>right</em> of the element).</li><li>Date, time, and datetime fields all render with the corresponding group of select menus.</li><li>If the field is the primary key of the model, it renders as a hidden field.</li></ul> Of course, you can always manually specify the type of element rendered using the <code>'type'</code> key of the <code>$options</code> array, which can be set to any one of the following values: <code>'hidden', 'checkbox', 'text', 'password', 'file', 'select', 'time', 'date', 'datetime',</code> or <code>'textarea'</code>. If the <code>'type'</code> key is unspecified, and the field type is not one of the above, it will render as a textarea. <p>In addition to rendering the input element itself, <code>input()</code> will also render a label, a wrapper <div> and any associated validation messages, if present. This is all by default, but you can customize the behavior, as in the following:</p> <code><?=$form->input('terms', array('label' => array('text' => 'Terms of service', 'class' => 'title'))); ?></code>
<p>Here, the <code>'label'</code> key has been defined as an array in order to specify custom rendering options for the <label> tag. You can also define <code>'label'</code> as a string (the text of the label itself), or false, to disable the rendering of the label.</p> <p>The <code>'div'</code> key works similarly for controlling the rendering of the wrapper div, except that assigning it a string sets the class name.</p> <p>Now, at the risk of being <em>too</em> meta, there's also a wrapper method for the wrapper method: <code>FormHelper::inputs()</code>. This method takes a single array parameter, which can be indexed, associative, or mixed. The array is simply a list of fields to be rendered with <code>FormHelper::input()</code>. By default, all fields are rendered with the default options, but you can use the associative array syntax to specify options for individual fields, as in the following:</p><p> <code><?=$form->inputs(array('first_name', 'middle_initial' => array('label' => 'MI'))); ?></code>
</p><p>Here, the <code>first_name</code> field would be rendered with defaults, but the <code>middle_initial</code> field would be rendered with custom label text. Using this syntax it is possible (though not always recommended ;-)) to render an entire form in one line of code.</p>
No comments:
Post a Comment