ENHANCEMENT Custom form attributes through Form->setAttribute()

This commit is contained in:
Ingo Schommer 2011-12-22 18:05:20 +01:00
parent 0dab75c3a0
commit 72694d8349
3 changed files with 98 additions and 25 deletions

View File

@ -145,6 +145,12 @@ class Form extends RequestHandler {
*/ */
protected $encType; protected $encType;
/**
* @var array Any custom form attributes set through {@link setAttributes()}.
* Some attributes are calculated on the fly, so please use {@link getAttributes()} to access them.
*/
protected $attributes = array();
/** /**
* Create a new form, with the given fields an action buttons. * Create a new form, with the given fields an action buttons.
* *
@ -576,6 +582,40 @@ class Form extends RequestHandler {
$this->actions->removeByName($name); $this->actions->removeByName($name);
} }
/**
* @param String
* @param String
*/
function setAttribute($name, $value) {
$this->attributes[$name] = $value;
}
/**
* @return String
*/
function getAttribute($name) {
return @$this->attributes[$name];
}
function getAttributes() {
$attrs = array(
'id' => $this->FormName(),
'action' => $this->FormAction(),
'method' => $this->FormMethod(),
'enctype' => $this->getEncType(),
'target' => $this->target,
'class' => $this->extraClass(),
);
if($this->validator && $this->validator->getErrors()) {
if(!isset($attrs['class'])) $attrs['class'] = '';
$attrs['class'] .= ' validationerror';
}
$attrs = array_merge($attrs, $this->attributes);
return $attrs;
}
/** /**
* Unset the form's dataField by its name * Unset the form's dataField by its name
* *
@ -603,37 +643,40 @@ class Form extends RequestHandler {
/** /**
* Return the attributes of the form tag - used by the templates. * Return the attributes of the form tag - used by the templates.
* *
* @return string The attribute string * @param Array Custom attributes to process. Falls back to {@link getAttributes()}.
* If at least one argument is passed as a string, all arguments act as excludes by name.
* @return String HTML attributes, ready for insertion into an HTML tag
*/ */
function FormAttributes() { function getAttributesHTML($attrs = null) {
$attributes = array(); $exclude = (is_string($attrs)) ? func_get_args() : null;
if(!$attrs || is_string($attrs)) $attrs = $this->getAttributes();
// Forms shouldn't be cached, cos their error messages won't be shown // Forms shouldn't be cached, cos their error messages won't be shown
HTTP::set_cache_age(0); HTTP::set_cache_age(0);
// workaround to include javascript validation // workaround to include javascript validation
if($this->validator && !$this->jsValidationIncluded) $this->validator->includeJavascriptValidation(); if($this->validator && !$this->jsValidationIncluded) $this->validator->includeJavascriptValidation();
$attrs = $this->getAttributes();
// Remove empty
$attrs = array_filter((array)$attrs, create_function('$v', 'return ($v || $v === 0);'));
// compile attributes // Remove excluded
$attributes['id'] = $this->FormName(); if($exclude) $attrs = array_diff_key($attrs, array_flip($exclude));
$attributes['action'] = $this->FormAction();
$attributes['method'] = $this->FormMethod(); // Create markkup
$attributes['enctype'] = $this->getEncType(); $parts = array();
if($this->target) $attributes['target'] = $this->target; foreach($attrs as $name => $value) {
if($this->extraClass()) $attributes['class'] = $this->extraClass(); $parts[] = ($value === true) ? "{$name}=\"{$name}\"" : "{$name}=\"" . Convert::raw2att($value) . "\"";
if($this->validator && $this->validator->getErrors()) {
if(!isset($attributes['class'])) $attributes['class'] = '';
$attributes['class'] .= ' validationerror';
} }
// implode attributes into string return implode(' ', $parts);
$preparedAttributes = ''; }
foreach($attributes as $k => $v) {
// Note: as indicated by the $k == value item here; the decisions over what to include in the attributes can sometimes get finicky function FormAttributes() {
if(!empty($v) || $v === '0' || $k == 'value') $preparedAttributes .= " $k=\"" . Convert::raw2att($v) . "\""; return $this->getAttributesHTML();
}
return $preparedAttributes;
} }
/** /**

View File

@ -1,5 +1,5 @@
<% if IncludeFormTag %> <% if IncludeFormTag %>
<form $FormAttributes> <form $AttributesHTML>
<% end_if %> <% end_if %>
<% if Message %> <% if Message %>
<p id="{$FormName}_error" class="message $MessageType">$Message</p> <p id="{$FormName}_error" class="message $MessageType">$Message</p>

View File

@ -340,9 +340,39 @@ class FormTest extends FunctionalTest {
$this->assertEquals('application/x-www-form-urlencoded', $form->getEncType()); $this->assertEquals('application/x-www-form-urlencoded', $form->getEncType());
} }
function testAttributes() {
$form = $this->getStubForm();
$form->setAttribute('foo', 'bar');
$this->assertEquals('bar', $form->getAttribute('foo'));
$attrs = $form->getAttributes();
$this->assertArrayHasKey('foo', $attrs);
$this->assertEquals('bar', $attrs['foo']);
}
function testAttributesHTML() {
$form = $this->getStubForm();
$form->setAttribute('foo', 'bar');
$this->assertContains('foo="bar"', $form->getAttributesHTML());
$form->setAttribute('foo', null);
$this->assertNotContains('foo="bar"', $form->getAttributesHTML());
$form->setAttribute('foo', true);
$this->assertContains('foo="foo"', $form->getAttributesHTML());
$form->setAttribute('one', 1);
$form->setAttribute('two', 2);
$form->setAttribute('three', 3);
$this->assertNotContains('one="1"', $form->getAttributesHTML('one', 'two'));
$this->assertNotContains('two="2"', $form->getAttributesHTML('one', 'two'));
$this->assertContains('three="3"', $form->getAttributesHTML('one', 'two'));
}
protected function getStubForm() { protected function getStubForm() {
return new Form( return new Form(
new Controller(), new FormTest_Controller(),
'Form', 'Form',
new FieldList(new TextField('key1')), new FieldList(new TextField('key1')),
new FieldList() new FieldList()