SymfonyÈ diffusa l’abitudine, quando si crea un menù a tendina, di inserire al primo posto un’opzione cosiddetta “neutra”, che magari inviti l’utente appunto ad operare una scelta (e da non scegliere effettivamente). Più o meno qualcosa del genere:

<select name="mySelect">
   <option disabled="disabled">-- seleziona --</option>
   <option value="1">Prima opzione</option>
   <option value="2">Seconda opzione</option>
</select>

Proprio perché le ultime due opzioni sono “reali”, a differenza della prima hanno un valore espresso tramite l’attributo value. La prima ha inoltre l’attributo disabled (opzionale), utile per disabilitare appunto l’opzione.

Se non si conosce questo attributo, si consulti la documentazione, da quale:

The disabled attribute specifies that a button should be disabled.
A disabled button is unusable and un-clickable.
The disabled attribute can be set to keep a user from clicking on the button until some other condition has been met (like selecting a checkbox, etc.). Then, a JavaScript is required to remove the disabled value, and make the button usable.

In Symfony sembra che non ci sia nulla per fare tutto questo: non è possibile non impostare l’attributo value, come non è possibile aggiungere l’attributo disabled. Value è l’unico attributo impostabile e per giunta obbligatorio (ci sono alternative, invece, per altri widget, come ad esempio sfWidgetFormDoctrineChoice o sfWidgetFormPropelChoice).
Il motivo è semplice: il widget che genera un menù a tendina, sfWidgetFormChoice (documentazione) accetta un array per popolare le opzioni, dove le chiavi dell’array saranno gli attributi value delle opzioni e i valori dell’array le loro relative etichette.

Il problema è che Php non può – per ovvi motivi – accettare valori per un array senza che tutti abbiano una relativa chiave, che altrimenti verrà sempre e comunque creata. Di conseguenza, il value delle opzioni, popolato a partire dalle chiavi, esisterà sempre, anche se magari è vuoto.

Ad esempio, impostando una chiave vuota:

$form->setWidget(new sfWidgetFormChoice(array('choices' => array('' => '-- seleziona --', '1' => 'Prima opzione', '2' => 'Seconda opzione'))));

Il codice generato sarà il seguente (value è vuoto, ma esiste comunque, e non è la stessa cosa):

<select name="mySelect">
   <option value="">-- seleziona --</option>
   <option value="1">Prima opzione</option>
   <option value="2">Seconda opzione</option>
</select>

Mentre invece, non indicando nessuna chiave per il primo elemento:

$form->setWidget(new sfWidgetFormChoice(array('choices' => array('-- seleziona --', '1' => 'Prima opzione', '2' => 'Seconda opzione'))));

Php, automaticamente, gli assegnerà la chiave 0 e quindi il codice generato sarà il seguente:

<select name="mySelect">
   <option value="">-- seleziona --</option>
   <option value="1">Prima opzione</option>
   <option value="2">Seconda opzione</option>
</select>

Infine, in nessun caso è possibile impostare l’attributo disabled.

Le soluzioni sono allora due:

  1. riscrivere il widget (sfWidgetFormChoice.class.php, sfWidgetFormChoiceBase.class.php e sfWidgetFormSelect.class.php, tutti in /lib/widget);
  2. modificare il form con jquery.

Ho scelto la seconda strada (buona fortuna a quelli che dovessero scegliere la prima…), nonostante non possa nascondere che l’altra sarebbe più brillante e pulita, sebbene molto più complessa.
In questo caso, il codice è breve e facilmente comprensibile: è sufficiente selezionare tutti gli option con value vuoto ma esistente (evitiamo invece di lavorare sugli 0 e nel widget sarà sempre meglio usare una chiave vuota, semmai poi dovessimo avere realmente bisogno di un option con value 0), rimuovere completamente l’attributo value e (opzionalmente) aggiungere l’attributo disabled con valore disabled:

$("document").ready(function() {
   $('option[value=""]').removeAttr("value").attr("disabled", "disabled");
});

XHTML - Puoi usare questi tag: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>