Multiple choice form elements

10 views
Skip to first unread message

Nick Lo

unread,
Oct 3, 2010, 12:54:48 AM10/3/10
to cobweb-dev
I've started working through making an equivalent to django form's
"CheckboxSelectMultiple" to make a list of checkboxes and realised it
would make sense to check if this has already been done? If so some
example code would be very useful.

Cheers,

Nick

Nick Lo

unread,
Oct 3, 2010, 1:40:55 AM10/3/10
to cobweb-dev
Somewhat answering my own question but also to get some feedback: Here
is my work in progress widget solution:

class MultipleCheckboxInput extends FormWidget {

function render(FormField $field, $data, $attributes = array()) {
$choices = $field->choices();
$index = array();
if(is_array($data)) {
foreach($data as $checked) {
$index[$checked] = array_key_exists($checked,
$choices);
}
}

$html = '<ul>';
foreach ($field->choices() as $value => $label) {
$html .= sprintf('<li><label for="%s"><input
type="checkbox" name="%s[]" id="%s" value="%s" %s /> %s</label></li>',
html_escape($field->name()) .
'_' .html_escape($value),
html_escape($field->name()),
html_escape($field->name()) .
'_' .html_escape($value),
html_escape($value),
!empty($index) && isset($index[$value]) ?
'checked="checked" ' : '',
html_escape($label)
);
}
return $html . '</ul>';
}

public function extract($field, $data) {
$values = $data->get($field->name());
$choices = $field->choices();
$index = array();
if(is_array($values)) {
foreach($values as $value) {
$index[$value] = array_key_exists($value, $choices);
}
}
if (!empty($index)) {
return $index;
}
return $values;
}
}

It looks like I'm going to have to make a MultipleChoiceField
FormField class as well as ChoiceField's clean() method doesn't allow
for multiple choices (ie $value = array() ):

public function clean($value) {
if ($this->isRequired() && !in_array($value, array_keys($this-
>choices)))
throw new FormValidationException($this-
>error_messages['invalid_choice']);

return $value;
}

Nick

Nick Lo

unread,
Oct 3, 2010, 1:50:19 AM10/3/10
to cobweb-dev

> It looks like I'm going to have to make a MultipleChoiceField
> FormField class as well as ChoiceField's clean() method doesn't allow
> for multiple choices (ie $value = array() ):
>
> public function clean($value) {
>     if ($this->isRequired() && !in_array($value, array_keys($this->choices)))
>
>         throw new FormValidationException($this-
>
> >error_messages['invalid_choice']);
>
>     return $value;
>
> }

Ignore the above! This is what happens when you've spent more time
doing Python and have to come back to PHP to remember the quirks of
its array functions, of course in_array does accept an array as it's
search value!

Nick

Nick Lo

unread,
Oct 3, 2010, 4:02:46 AM10/3/10
to cobweb-dev
> Ignore the above! This is what happens when you've spent more time
> doing Python and have to come back to PHP to remember the quirks of
> its array functions, of course in_array does accept an array as it's
> search value!

Although it does accept an array it doesn't do the check needed. Here
is a MultipleChoiceField class that works for my needs:

class MultipleChoiceField extends ChoiceField {
public function clean($values=array()) {
if(true !== $this->isRequired()) {
return $values;
}
if(is_array($values)) {
foreach($values as $value) {
if (in_array($value, array_keys($this->choices),
true)) {
return $values;
}
}
}
throw new FormValidationException($this-
>error_messages['invalid_choice']);
}
}

Might be useful for someone.

Nick

Øystein Riiser Gundersen

unread,
Oct 3, 2010, 5:45:30 PM10/3/10
to cobwe...@googlegroups.com
Excellent!

I wrote something similar for a site I built once, but never got around to committing it. I'll have a look at this and add `MultipleChoiceField` as soon as possible (with credit where credit is due :).

Question: Should "<select multiple>...</select>" be the default widget for this field? (A list-of-checkboxes widget should be added as well, for people who need this.)

> --
> You received this message because you are subscribed to the Google Groups "cobweb-dev" group.
> To post to this group, send email to cobwe...@googlegroups.com.
> To unsubscribe from this group, send email to cobweb-dev+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/cobweb-dev?hl=en.
>

Nick Lo

unread,
Oct 3, 2010, 9:02:06 PM10/3/10
to cobweb-dev
> I wrote something similar for a site I built once, but never got around to committing it. I'll have a look at this and add `MultipleChoiceField` as soon as possible (with credit where credit is due :).

Ha, thanks, though I'm not worried about getting credit. My solution
was just that, a somewhat messy solution to my current needs rather
than an ideal approach. Do with it what you will.

> Question: Should "<select multiple>...</select>" be the default widget for this field? (A list-of-checkboxes widget should be added as well, for people who need this.)

Yes, as otherwise a user can so easily add the multiple attribute into
the current ChoiceField, only to find it doesn't work as expected, so
you have a bit of a gap there.

Nick
Reply all
Reply to author
Forward
0 new messages