Symfony: Domptez les filtres de l’admin generator

system-run Un détail qui m’a toujours titillé dans le fabuleux admin generator de symfony, c’est le bloc de filtre. Le concept est bien sûr génial. Sans rien faire, vous avez déjà la possibilité de filtrer vos résultats, un gain de temps énorme, surtout quand on a un client qui sait ce qu’il veut. Mais voilà, même si depuis la 1.2, le layout de l’admin generator par défaut a subit un lifting qui le rend beau de série:
Image 56

On rencontre très vite, dans le cas d’un tableau avec beaucoup de colonnes, le fameux « bug » css sur un écran plus petit que mon 20″ (oui parce que chez moi, c’est toujours très beau, chez mes chefs de projets et leur portable, beaucoup moins :D):
Image 57

Alors bien sûr, la solution radicale, c’est de réduire le nombre de colonnes, mais souvent le client, il les veut ses colonnes! La 2e solution est de supprimer ce bloc de filtre. On fait ça très simplement dans le generator.yml:

filter:
  class: false

Cependant, il arrive quand même que le filtrage soit nécessaire mais bien souvent, seulement 2 ou 3 valeurs. J’ai donc décidé de prendre le taureau par les cornes et faire la modification dont je rêve depuis longtemps, passer ce bloc de filtre, au dessus du tableau! Pour ce faire, j’ai modifié 2 fichiers. Tout d’abord, le fichier _filters.php qu’il faudra rajouter dans le dossier templates de vos modules visés:

<div class="sf_admin_filter">
 
	<div class="content_filter">
  <?php if ($form->hasGlobalErrors()): ?>
    <?php echo $form->renderGlobalErrors() ?>
  <?php endif; ?>
 
 
  <form action="<?php echo url_for('produits_collection', array('action' => 'filter')) ?>" method="post">
	  <?php foreach ($configuration->getFormFilterFields($form) as $name => $field): ?>
	  <div class="bloc_filter">
        <?php if ((isset($form[$name]) && $form[$name]->isHidden()) || (!isset($form[$name]) && $field->isReal())) continue ?>
          <?php include_partial('produits/filters_field', array(
            'name'       => $name,
            'attributes' => $field->getConfig('attributes', array()),
            'label'      => $field->getConfig('label'),
            'help'       => $field->getConfig('help'),
            'form'       => $form,
            'field'      => $field,
            'class'      => 'sf_admin_form_row sf_admin_'.strtolower($field->getType()).' sf_admin_filter_field_'.$name,
          )) ?>
    </div>
    <?php endforeach; ?>
 
     <?php echo $form->renderHiddenFields() ?>
     <?php echo link_to(__('Reset', array(), 'sf_admin'), 'produits_collection', array('action' => 'filter'), array('query_string' => '_reset', 'method' => 'post')) ?>
     <input type="submit" value="<?php echo __('Filter', array(), 'sf_admin') ?>" />
  </form>
  </div>
</div>

Au final, j’ai simplement supprimé le tableau, par défaut et mis chaque widget dans un div. On obtient donc quelque chose qui change pas vraiment la donne pour l’instant:
Image 58

Mais en lui appliquant un peu de css:

div#sf_admin_bar {
	float:none;
	margin: 0;
}
 
#sf_admin_bar .sf_admin_filter form div.bloc_filter {
	display:inline;
	padding:0 20px 0 0;
}
 
div#sf_admin_container #sf_admin_bar label {
	display:inline;
	float:none;
	padding:0;
}

On commence à approcher de ce que l’on souhaite:
Image 60

Maintenant, on habille un peu la chose, histoire de gagner en clarté:

#sf_admin_bar .sf_admin_filter {
	background-color:#FFF;
	margin:12px 0;
}
 
#sf_admin_bar .sf_admin_filter .content_filter {
	border:1px solid #DDDDDD;
	padding:5px;
}

Pour obtenir finalement:
Image 61

Un dernier détail, le filtre « référence » avec sa colonne « is_empty » casse un peu notre rendu. Personnellement, je ne me sers pas de cette checkbox, on va donc redéfinir notre filtre pour la supprimer dans lib/filters/MonModuleFilters.class.php:

public function configure()
  {
    $this->widgetSchema['reference'] = new sfWidgetFormFilterInput(array(
      'template' => '%input%'
    ));
  }

Et voilà, une jolie barre de recherche beaucoup plus du goût des clients en général :)
Image 62

Alors bien sûr, cette solution ne fonctionne qu’avec un nombre limité de filtre, sinon on aurait un rendu un peu moins visuel, mais je pense que ça reste toujours mieux que 2 blocs qui se chevauchent.

Tags: , , , ,

A propos de l'auteur

Tim

Développeur web spécialisé Symfony, il est avant tout passionné de web tout simplement. Il aime les défis et farfouiller dans le code de Symfony ou Doctrine. Fondateur du blog, il exerce chez Autrement.

Vous avez aimé ce billet? Faites le savoir!

  • Delicious
  • Twitter
  • Technorati Favorites
  • FriendFeed
  • Google Bookmarks
  • Share/Bookmark

8 Réponses

  1. Sebastien 5 août 2009 à 12 h 24 min #

    Pour enlever la checkbox on peut faire ça aussi :

    public function configure()
    {
        $this->widgetSchema['reference'] = new sfWidgetFormFilterInput(array(
          'with_empty' => false
        ));
    }
    
  2. Tim 5 août 2009 à 13 h 44 min #

    Bien vu, et c’est plus dans la logique je pense. Merci : )

  3. Sebastien 5 août 2009 à 15 h 39 min #

    N’ayant pas (encore :( )de blog, je me permet de diffuser sur le tien, en plus de la proprieté ‘with_empty’, j’ai cherché un peu plus en profondeur dans le CSS et après moult efforts :P, j’ai enfin réussi à faire ce que je voulais.

    En gros, placé le bloc de filtre comme tu le fais (faut avouer que c’est beaucoup plus pratique), SANS toucher au template « _filter.php ».

    Voici le code CSS nécessaire, je l’ai appliqué sur 2 pages d’un backend possédant des filtres et ça à pas posé de soucis.

    #sf_admin_container #sf_admin_bar {
    	float:none;
    	margin: 0px;
    }
    #sf_admin_container #sf_admin_bar .sf_admin_filter table tr {
    	clear: none;
    	border: 1px solid #DDDDDD;
    	padding: 0px;
    }
    #sf_admin_container #sf_admin_bar .sf_admin_filter table tr td {
    	height: 50px;
    	vertical-align: middle;
    	border: none;
    }
    #sf_admin_container #sf_admin_bar .sf_admin_filter table tbody {
    	clear: none;
    	float: left;
    }
    #sf_admin_container #sf_admin_bar .sf_admin_filter table tbody tr {
    	float: left;
    	border-right: none;
    }
    #sf_admin_container #sf_admin_bar .sf_admin_filter table tfoot {
    	clear: none;
    	float: right;
    }
    #sf_admin_container #sf_admin_bar .sf_admin_filter table tfoot tr {
    	float: right;
    }
    

    Testé pour les input et les selectbox, j’ai pas encore eu l’occasion de le faire pour les checkbox et radiobox par contre.

    Seule les multi-selectbox devraient poser problème, la solution serait surement d’augmenter le « height » du td. On peut le mettre à 40px si on enlève les is_empty, ça réduit un peu la ligne, sinon 50px avec ou sans c’est plus propre je trouve.

    Rendu chez moi :
    http://img23.imageshack.us/img23/5087/cssfitre.png

    Voilà :)

  4. Tim 5 août 2009 à 16 h 51 min #

    Nice!

    Aucun souci pour contribuer via commentaire, et d’ailleurs si t’es intéressé pour y contribuer directement, on peut toujours en discuter : )

  5. Guillaume 17 août 2009 à 14 h 40 min #

    Cher Tim

    Merci pour ton billet il m’est très utile pour personnaliser mon application.

    Cependant, j’ai trouvé le _filters.php de base dans monprojet/cache/monprojet/dev/modules/autoMonmodule/templates/ car le tiens ne marche que pour ton module (bon je sais c’est juste deux trois mots à remplacer ^^)

    J’ai trouvé ça dans le cache de google : http://209.85.229.132/search?q=cache:IFQpjw5cMLUJ:trac.symfony-project.org/changeset/1485%3Fformat%3Dzip%26new%3D1485+symfony+customize+_filters.php&cd=1&hl=fr&ct=clnk&gl=fr

    Cordialement,

  6. Tim 17 août 2009 à 17 h 43 min #

    Exact, je n’ai pas précisé, mais c’était le truc à faire, le récupérer dans le cache.

    J’essaierai d’éditer quand j’aurais le temps.

    Merci bien ;)

  7. Tiayb 18 août 2009 à 14 h 34 min #

    Pour enlever la checkbox on peut faire ça également :
    public function configure()
    {
    $this->widgetSchema['reference']->setOption(‘with_empty’, false);
    }

  8. rastaferraille 9 mars 2010 à 11 h 28 min #

    Le code de sebastien est nickel (pas besoin de toucher au php, donc plus portable) mais il ne fonctionne malheureusement pas avec IE (clear: none). Les infos ne s’affichent pas en ligne.

    Quelqu’un sait comment corriger ça ?


Laisser un message