Je vais vous montrer dans cet article comment mettre en place rapidement un datePicker jQuery dans un formulaire Symfony 1.2

Pré-requis

Fichiers externes

  • Télécharger jQuery UI
    (jquery-1.3.2.min.js, jquery-ui-1.7.1.custom.min.js)

    Vous pouvez télécharger une version « customizée » de jQuery UI ici :
    Télécharger JQuery UI

  • Version française
    (uidatepicker-fr.js)

    Vous trouverez le patch français de ce plugin ici :

    Datepicker jQuery en français

  • Intégration dans Symfony
    1. JS
      Copiez les fichiers :
      [jquery UI]/js/jquery-1.3.2.min.js
      [jquery UI]/js/jquery-ui-1.7.1.custom.min.js
      uidatepicker-fr.js
      directement dans [votre_projet]/web/js
    2. CSS
      • Copiez le fichier :
        [jquery UI]/css/jquery-ui-1.7.1.custom.css dans :
        [votre_projet]/web/css.
      • !! Attention !! :
        J’ai dû remplacer toutes les occurrences de :
        url(images/ par :
        url(../images/
    3. Images
      N’oubliez pas de copier le contenu de :
      [jquery UI]/css/smoothness/images dans :
      [votre_projet]/web/images

View.yml

N’oubliez pas de faire référence aux fichiers externes dans le view :

default:
  http_metas:
    content-type: text/html

  metas:
    #title:        symfony project
    #description:  symfony project
    #keywords:     symfony, project
    #language:     en
    #robots:       index, follow

  stylesheets:    [main.css, jquery-ui-1.7.1.custom.css]

  javascripts:    [jquery-1.3.2.min.js, uidatepicker-fr.js, jquery-ui-1.7.1.custom.min.js]

  has_layout:     on
  layout:         layout

sfWidgetFormJQueryI18nDate.class.php

J’ai modifié la classe sfWidgetFormJQueryDate pour qu’elle soit compatible avec un format de date français.
De plus, on peut facilement configurer les options du widget jQuery.

  • Code source :
    Fichier : sfWidgetFormJQueryI18nDate.class.php
    Chemin : /plugins/sfFormExtraPlugin/lib/widget/

    
     * 
     * For the full copyright and license information, please view the LICENSE
     * file that was distributed with this source code.
     */
    
    /**
     * sfWidgetFormJQueryDate represents a date widget rendered by JQuery UI.
     *
     * This widget needs JQuery and JQuery UI to work.
     *
     * @package    symfony
     * @subpackage widget
     * @author     Fabien Potencier 
     * @version    SVN: $Id: sfWidgetFormJQueryDate.class.php 12875 2008-11-10 12:22:33Z fabien $
     */
    class sfWidgetFormJQueryI18nDate extends sfWidgetFormI18nDate
    {
      /**
       * Configures the current widget.
       *
       * Available options:
       *
       *  * image:   The image path to represent the widget (false by default)
       *  * config:  A JavaScript array that configures the JQuery date widget
       *  * culture: The user culture
       *
       * @param array $options     An array of options
       * @param array $attributes  An array of default HTML attributes
       *
       * @see sfWidgetForm
       */	
    
      protected function configure($options = array(), $attributes = array())
      {
        $this->addOption('image', false);
        $this->addOption('config', $options["config"]);
        $this->addOption('culture', $options["culture"]);
        $this->addOption('years', $options["years"]);
    
        parent::configure($options, $attributes);
    
        if ('en' == $this->getOption('culture'))
        {
          $this->setOption('culture', 'en');
        }
      }
    
      /**
       * @param  string $name        The element name
       * @param  string $value       The date displayed in this widget
       * @param  array  $attributes  An array of HTML attributes to be merged with the default HTML attributes
       * @param  array  $errors      An array of errors for the field
       *
       * @return string An HTML tag string
       *
       * @see sfWidgetForm
       */
      public function render($name, $value = null, $attributes = array(), $errors = array())
      {
        $prefix = $this->generateId($name);
    
        $image = '';
        if (false !== $this->getOption('image'))
        {
          $image = sprintf(', buttonImage: %s, buttonImageOnly: true', $this->getOption('image'));
        }
        return parent::render($name, $value, $attributes, $errors).
               $this->renderTag('input', array('type' => 'hidden', 'size' => 10, 'id' => $id = $this->generateId($name).'_jquery_control', 'disabled' => 'disabled')).
               sprintf(<<
      
      function %s_read_linked()
      {
        \$("#%s").val(\$("#%s").val() + "/" + \$("#%s").val() + "/" + \$("#%s").val());
    
        return {};
      }
    
      function %s_update_linked(date)
      {
        \$("#%s").val(date.substring(0, 2));
        \$("#%s").val(parseInt(date.substring(3, 5), 10));
        \$("#%s").val(date.substring(6, 10));
      }
    
      \$("#%s").datepicker(\$.extend({}, {
        minDate:    new Date(%s, 1 - 1, 1),
        maxDate:    new Date(%s, 12 - 1, 31),
        onSelect:   %s_update_linked,
        beforeShow: %s_read_linked,    
        %s    
        showOn:     "both"
        %s
      }, \$.datepicker.regional["%s"]));
    
    
    EOF
          ,
          $prefix, $id,
          $this->generateId($name.'[day]'), $this->generateId($name.'[month]'), $this->generateId($name.'[year]'),
          $prefix,
          $this->generateId($name.'[day]'), $this->generateId($name.'[month]'), $this->generateId($name.'[year]'),
          $id,
          min($this->getOption('years')), max($this->getOption('years')),
          $prefix, $prefix, $this->getOption('config'), $image, $this->getOption('culture')
        );
      }
    }
    
  • Explication des modifications :
    1. Ligne 20 :
      Notre widget dérive désormais de sfWidgetFormI18nDate

      class sfWidgetFormJQueryDate extends sfWidgetFormI18nDate
      
    2. Lignes 40, 41 et 42:
      On ajoute les options « config », « culture » et « years » avec le paramètre « options » de la fonction « configure » :

        $this->addOption('config', $options["config"]);
        $this->addOption('culture', $options["culture"]);
        $this->addOption('years', $options["years"]);
      
    3. Lignes 85 et 86
      • Il faut inverser l’ordre du jour et du mois pour être compatible avec un format français, ce qui revient dans un sprintf, à changer l’ordre des lignes dans le code.
      • Il faut faire un parseInt sur le mois pour transformer « 01 » en « 1 », parseInt est la fonction javascript permettant de caster une chaîne de caractères en Integer :
        Premier paramètre : la chaîne à caster (ici : date.substring(3, 5) )
        Deuxième paramètre : Le système numérique à utiliser (ici décimal : 10)
          \$("#%s").val(date.substring(0, 2));
          \$("#%s").val(parseInt(date.substring(3, 5), 10));
      
    4. Lignes 95 et 109
      • On passe les options directement dans le premier argument.
        Le %s de la ligne 95 correspond au $this->getOption(‘config’) de la ligne 109
        Le %s de la ligne 98 correspond au $this->getOption(‘culture’) de la ligne 109
      • Ligne 109 : passage des options et da la culture au widget.
      $prefix, $prefix, $this->getOption('config'), $image, $this->getOption('culture')
      

Exemple d’utilisation

  • Schéma
    person:
      columns:
        [...]
        birthday:
          type: timestamp
        [...]
    
  • Formulaire (Instanciation du widget)
      [...]
      public function configure()
      {
        for($i = 1900; $i<2010; $i++)
        {
          $years[$i] = $i;
        }
        $this->widgetSchema['birthday'] = new sfWidgetFormJQueryI18nDate(
          array('config' => 'yearRange: \'1900:2009\', 
                               changeYear: true, 
                               changeMonth: true,',
                'culture' => 'fr',
                'years'=> array_combine($years, $years))
          );   
      }
      [...]
    
  • Aperçu
    jquery datepicker fr

Sources

Previous ArticleNext Article

This post has 17 Comments

17
  1. Salut,
    Merci pour ce billet qui m’aide à implementer ce calendrier.
    Mais le plugin que j’ai telechargé sur le site de symfony je n’ai pas ce fichier sfWidgetFormJQueryI18nDate.class.php à l’endroit indiqué /plugins/sfFormExtraPlugin/lib/widget/ ,j’ai plutot celui sfWidgetFormJQueryDate.class.php ou vous aviez renommé ce fichier pour avoir l’autre.
    Priere me donner des pistes.
    Merci d’avance.

  2. Salut,
    Oui j’ai renommé le fichier, et je l’ai modifié pour qu’il gère l’i18n. La classe hérite de ‘sfWidgetFormI18nDate’ et plus de ‘sfWidgetFormDate’.
    Merci pour l’intérêt que vous portez au blog de Lexik =)

  3. Bonjour,

    merci pour ce petit tuto, tout marche bien à l’exception d’une petite chose :

    Quand je choisis une date avec le calendrier, il n’y a que les 3 derniers mois qui fonctionnent. Par exemple si je sélectionne une date en mars, le jour et l’année s’affichent correctement dans la partie gauche mais le moi reste vide …

    Si vous avez une idée je suis preneur.

    Bye

  4. Merci pour ce tutoriel.
    C\’est à deux doigts de fonctionner pour moi, mis à part le fait que les mois et les jours sont inversés ! Je m\’explique :
    Les champs du formulaire contiennent \"12 mars 2008\", et dans le widget jQuery, la date par défaut est 3 décembre 2008\". 12/03 correspond à 03/12 et inversement.

    Sur votre exemple, on est au 08/08/1979, forcément ça fonctionne dans les deux sens !

    Vous n\’avez pas ce souci pour les autres dates ?

  5. Encore un merci pour ce tutoriel,
    Je débute avec Symfony (1.2) et je me retrouve à travailler sur un projet conséquent.
    Votre blog, en général, m\’ai d\’un grand secoure pour comprendre de nombreuses subtilités de ce framework !

    Merci encore !

    PS: Pas de souci pour aucunes dates en ce qui me concerne …

  6. Hello,

    Pour rendre un peu plus français le widget, je rajoute un config en plus : firstDay: 1, ce qui fait commencer la semaine au lundi.

  7. Merci pour ce tuto.

    J’aimerai n’avoir qu’un champ date au lieu d’avoir 3 champs : jour, mois et année. Que dois-je changer ?

    Merci d’avance,

    Symfony 1.4
    Netbeans 6.8
    php 5.3

  8. Merci pour ce tuto qui m’a permis d’implémenter le datepicker, non sans mal ceci dit ! mais ça fonctionne.

    Par contre, comment fait-on pour inverser l’ordre des select jour et mois ? J’ai toujours le select mois avant le select jour…

    Bon courage pour la suite, continuez comme ça !

  9. merci pour ce tuto mais j\’ai un petit probleme

    mon probleme c\’est que j\’ai eu le calendreir et tou vas bien mais lorsque je selectionne une date j\’aurais toujours un ou deux champs (jour et mois) manquant
    j\’ai toujour des valeur vide dans ce deux liste

    je ne sais pas d\’où provient cette erreur

  10. merci pour ce tuto mais j\\\’ai un petit probleme

    mon probleme c\\\’est que j\\\’ai eu le calendreir et tou vas bien mais lorsque je selectionne une date j\\\’aurais toujours un ou deux champs (jour et mois) manquant
    j\\\’ai toujour des valeur vide dans ce deux liste

    je ne sais pas d\\\’où provient cette erreur

  11. Bonjour,

    J’essaie d’implémenter sur le même principe un widget qui gère aussi l’heure, comme ici => http://trentrichardson.com/examples/timepicker

    Quelqu’un est-il déjà passé par là? J’ai commencé par étendre la classe à sfWidgetFormI18nDateTime et vu que c’est jquery qui gère, je ne vois pas trop quelles options passer à la méthode getTimeWidget()..

    Si quelqu’un a une idée je suis preneur 🙂

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *