Angular - injecter des directives via une directive de type attribut

Voici un petit besoin que j'avais sur un projet:

J'utilisais la librairie angular "ng-scrollbars" pour avoir des scrollbars un peu fancy. Nous devons alors spécifier dans notre HTML l'attribut "ng-scrollbars".

Parfois, pour certains éléments, l'aspect devait être différent. Du coup, conjointement, nous spécifions alors l'attribut "ng-scrollbars-config".

Et comme le projet est un composant, il faut que certains style personnels n'impacte pas l'application "host". Du coup, nous rajoutions alors notre classe CSS au même niveau que les deux attributs précédents.

D'un point de vue usage, cela le code compliqué, car nous devons bien penser à chaque fois que nous voulons utiliser un scrollbar, mettre la classe CSS. Et si nous avons un besoin de config, de spécifier un autre attribut.

Cela pose également le soucis d'évolution: si nous changeons pour une raison X ou Y le nom de la classe CSS (ou si nous devons un ajouter un autre), ou tout simplement nous voulons changer de composant angular pour les scrollbars.


Voici une petite recette de cuisine afin de créer une directive Angular de type attribut qui se chargera d'injecter tout ce nous avons besoin et dont l'usage sera plus simple et l'évolution centralisée:

/**
 * @name ng.directive:myScroll
 * @attribute myScroll
 * @example
 <div my-scroll="{ 'autoHideScrollbar': true }">
   <!-- A lot of stuff -->
 </div>
 */

(function (angular) {
  'use strict';

  function myScroll(
    $compile
  ) {
    return {
      'priority': 1001, // compiles first
      'terminal': true, // prevent lower priority directives to compile after it
      'restrict': 'A',
      'compile': function($element, $attrs){
        var scrollbarsConfig = $attrs.myScroll;

        $element.removeAttr('my-scroll'); // necessary to avoid infinite compile loop
        $element.attr('ng-scrollbars', '');
        $element.addClass('my-scroll'); // Inject my custom css class

        if (scrollbarsConfig) {
          $element.attr('ng-scrollbars-config', scrollbarsConfig);
        }

        return {
          'post': function postLink($scope, $targetedElement) {
            $compile($targetedElement)($scope);
          }
        };
      }
    };
  }

  myScroll.$inject = [
    '$compile'
  ];

  angular
    .module('myApp')
    .directive('myScroll', myScroll);

}(window.angular));// eslint-disable-line angular/window-service


Enjoy !

Commentaires

Posts les plus consultés de ce blog

ISO: liens & outils utiles

NodeJs et SSL: une petite analyse

Créer sa commande slack en quelques minutes