Rendre un élément scrollable avec Angular


Petit snippet que j’utilise dans mes apps angular. Ça permet de définir un comportement quand l’utilisateur scrolle au-dessus d’un élément. Typiquement, augmenter la valeur d’un champ, faire défiler un carousel, etc. Il faut, bien entendu, éviter que la page scrolle elle-même.

Implémentation

app.directive('wheelable', function() {
"use strict";
 
  /* On définit sur quels attributs on va mettre les callbacks */
  var directive = {
      scope: {
          'onWheelUp': '&onwheelup',
          'onWheelDown': '&onwheeldown'
      }
  };
 
  /* On limite la directive aux attributs */
  directive.restrict = 'A';
 
  /* Le code qu'active la directive quand on la pose sur l'élément */
  directive.link = function($scope, element, attributes) {
 
      /* On attache un callback à tous les événements de scrolling */
      element.bind('mousewheel wheel', function(e) {
 
        /* On vérifie si l'utilisateur scroll up ou down */
        if (e.originalEvent) {
          e = e.originalEvent;
        }
        var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY;
        var isScrollingUp = (e.detail || delta > 0);
 
        /* On appelle le bon callback utilisateur */
        if (isScrollingUp){
          $scope.$apply($scope.onWheelUp());
        } else {
          $scope.$apply($scope.onWheelDown());
        }
 
        /* On évite que la page scrolle */
        e.preventDefault();
      });
  };
 
  return directive;
});

Usage

Comme pour toutes les directives qui impliquent des callbacks, il faut définir des fonctions et les attacher à votre scope dans un controleur (ou un service attaché au controleur) :

app.controller('FooCtrl', function($scope) {
"use strict";
  $scope.votreCallBackPourQuandCaScrollDown = function(){
    // faire un truc par exemple moi je l'utilise pour changer
    // la valeur de l'élément.
  };
  $scope.votreCallBackPourQuandCaScrollDown = function(){
    // faire un autre truc
  };
});

La directive s’utilise en mettant l’attribut wheelable sur l’élément qu’on veut rendre scrollable. Ensuite on déclare dans les attributs onwheeldown et onwheelup le code à exécuter, et zou :

<div ng-controller="FooCtrl">
  ...
  <input type="text" wheelable
         onwheeldown="votreCallBackPourQuandCaScrollDown()"
         onwheelup="votreCallBackPourQuandCaScrollUp()"
         >
  ...
</div>

8 thoughts on “Rendre un élément scrollable avec Angular

  • Trq

    Vu les récents articles, il va falloir changer le titre de votre page principale :

    “Sam & Max: Javascript, WAMP, Git et du cul” :D

  • ytown

    On change l’audimat !
    Il y aura de plus en plus de javascript kiddies et bigottes chez qui sm et python fesait trop peur.

    Non sérieux, continue comme ça Sam, peut être arriveras-tu, un jour, à me faire faire du javascript.

  • Shagshag

    Fut un temps où un code comme ça t’aurait coûté la chaise électrique ou un bambou dans le fion.

    Apparemment maintenant tout le monde s’en fout de la validité HTML. Si ça fonctionne c’est bon.

    Donc pour que ce soit valide HTML5 faut écrire :

    <div data-ng-controller="FooCtrl">
      ...
      <input type="text" data-wheelable="wheelable"
             data-onwheeldown="votreCallBackPourQuandCaScrollDown()"
             data-onwheelup="votreCallBackPourQuandCaScrollUp()"
       >
      ...
    </div>

    Et du coup faut adapter le javascript.

  • foxmask

    @shagshag t’as utilisé le bouton “code” ? si oui la prochaine fois essaie avec

    <pre lang="python/javascript/php/html/autre">
    lecode
    < /pre>

    genre là pour moi ca a marché

  • Sam Post author

    @Shagshag : il me semble qu’en HTML5 les attributs arbitraires sont autorisés.

  • Shagshag

    @foxmask: oui le bouton code. Je note pour la prochaine fois.

    @Sam: seulement s’il commence par data- ( https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#data-* )

    Pour dire que maintenant tout le monde s’en fout d’être valide HTML :

    Best Practice: Prefer using the dash-delimited format (e.g. ng-bind for ngBind). If you want to use an HTML validating tool, you can instead use the data-prefixed version (e.g. data-ng-bind for ngBind). The other forms shown above are accepted for legacy reasons but we advise you to avoid them.

    Depuis la doc d’angularjs ( https://docs.angularjs.org/guide/directive )

    Autrement dit : faut faire de la forme ng-bind et si vous voulez passer la validation HTML data-ng-bind (mais seulement si, c’est une option, le mieux ng-bind)

  • Sam Post author

    Bien vu. C’est bon à savoir. Ca me fait rire quand je repense à toute mon époque des années 2000 à être un nazi sur la validation xhtml, à toujours recherche la forme la plus belle sur alsacreation.

  • clem

    @sam:

    il me semble qu’en HTML5 les attributs arbitraires sont autorisés.

    tolérés seulement, tolérés seulement…

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.