Making a choice (select) widget read-only in Symfony

I have a form in Symfony that contains a Choice widget (my database field is called created_group) and I need to show its value to the user but make it not editable, so that the user cannot change the value.

Using the HTML disabled attribute won’t work:

   $this -> widgetSchema['created_group']->setAttribute(‘disabled’,'disable’);

as this will show the select field as blurred and thus show the content, but the selected option won’t be sent on a form submit: Symfony will mark that field as missing and will save it as NULL in the database, or generate a database error if the field cannot be NULL. The more complicated solution would be to also make Symfony skip that field in updates / creation.

The simpler solution is to create a custom widget type that just shows the Select’s option text and adds a hidden field with the Select’s option value. This way the users sees the text and Symfony gets the correct value upon update. This solution assumes that you trust that the user won’t tamper the hidden field with things like Firebug, so keep in mind that it’s not a secure option to make that field read-only and to make sure that the user cannot change it. It’s more of a cosmetic option.

You must create a custom widget class. The class’s code is the following:

<?php
class sfReadonlySelect extends sfWidgetFormDoctrineChoice
{
public function render($name, $value = null, $attributes = array(), $errors = array())
{
$choices = $this->getChoices();
$string = $choices[$value];
$string.= ‘<input type=”hidden” name=”‘.escape_once($name).’” value=”‘.escape_once($value).’”/>’;
return $string;
}
}

all you need to do is to save that in a file called sfReadonlySelect.class.php in the /lib/widget/ directory of your installation.

Then in your /lib/form/doctrine/myForm.php class (where myForm is the name of the object to which your Select field belongs) you initialize  the field as following:

$this -> setWidget ( ‘created_group’, new sfReadonlySelect (array(‘model’ => $this->getRelatedModelName(‘GroupCreated’), ‘add_empty’ => true)) );

It’s a simple solution to a fairly simple problem, but I haven’t found a better one on the web so here it is! Please leave your comments/questions below.

 

 

Hiding option groups (optgroups) in Chrome and Internet Explorer with Jquery

If you need to hide a series of optgroups with Jquery, it is easy to do so in Firefox: you just need to call $(this).hide() on the option group, and it and all its children will be hidden and not selectable. If you want to show them back, you just need to call $(this).show() and they will reappear.

However, other browser like Chrome and IE don’t allow this: the style rule (display:none) is applied to the element but does not work, and the elements stay visible. I’ve found out a quick workaround for this problem.

Basically, all you need to do is to

  1. disable all the options within the optgroup (and deselect them if they are selected)
  2. move the optgroup to the end of the select’s optgroups, so that it does not get in the way

If you want to reinstate that optgroup (make it selectable again), you must do the opposite:

  1. enable all the options within the optgroup
  2. move the optgroup to the beginning of the select’soptgroups, so that it is visibile again.

I’ve created a couple of custom jquery functions for the purpose:

$.fn.hideOptionGroup = function() {
 $(this).hide();
 $(this).children().each(function(){
 $(this).attr("disabled", "disabled").removeAttr("selected");
 });
 $(this).appendTo($(this).parent());

}

$.fn.showOptionGroup = function() {
 $(this).show();    
 $(this).children().each(function(){
 $(this).removeAttr("disabled" );
 });
 $(this).prependTo($(this).parent());
 $(this).parent().animate({scrollTop:0},0);
}

You apply the function to the optgroup as follows:

$("#myOptgroupId").showOptionGroup();
$("#myOptgroupId").hideOptionGroup();

What this functions do is:

  1. hide/show the element in Firefox directly.
  2. then, it disables/enables all of the optgroup’s options.
  3. and moves it to the end/beginning of the select’s optgroups.
  4. scrolls the select to the top, so that the first optgroup is shown even if the user had scrolled down and selected something else (only for the show function).

This has been tested with Chrome, will test it with Explorer soon. Hope this helps. Comments and suggestions are welcome.

Converting to Title Case in MySQL – Capitalizing MySQL (a PHP solution)

Ever found some tables in your MySQL database with user-compiled data that is not coherent in terms of case? Some entries are in Title Case, some are all in UPPER CASE, some are all in lower case. If you need to switch everything to upper case or lower case, it’s as easy as typing the following query:
UPDATE `table` SET `field` = UPPER(`field`)
(For lower case, just use LOWER() instead of UPPER() ).

Continue reading

Coming soon…

HCE Web Design is preparing its own blog and working on new, upcoming site which will soon be online with graphics and services renewed.

For the moment, if you want to know who we went on our current website:

HCE Web Agency site

… And do not forget to reconnect early to observe the forthcoming news from HCE Hypertext Cultural Experiences!