Auzy
Auzy

Reputation: 2155

Angular Directive only works on one element at a time

I have the following angular directive. It uses a range slider to scroll a horizontal div of items. It works if applied to only one row. But if applied to multiple...nothing happens. The transclusion works, but function never runs and no errors are given. What can I do to this to make it be more angular universal and work on multiple elements? Here is repro:CodePen

app.directive('bob', function () {
        return {
            restrict: 'A',
            transclude: true,
            template:
            `<div style="background-color: #333"><input type="range" value="0" id="scroll-rangeb"><div id="photo-containerb" style="display: flex; overflow-x: scroll; flex-direction: row; align-items: center; height: 90%;" ng-transclude></div></div>`,
            link: function (scope, element, attrs) {
                var scroll = document.getElementById("scroll-rangeb");
                scroll.oninput = function () {
                    var panel = document.getElementById("photo-containerb");
                    var total = panel.scrollWidth - panel.offsetWidth;
                    var percentage = total * (this.value / 100);
                    panel.scrollLeft = percentage;
                }
            }
        };
    });

Upvotes: 0

Views: 867

Answers (1)

lenilsondc
lenilsondc

Reputation: 9800

#scroll-rangeb is a unique element (in theory), if you override the oninput on every directive it clearly will not work, it'll remain only the first one found. Anyways, you mustn't use multiple components with the same id at all. Try to find it from the element parameter given on the link function instead, using classes or somthing else.

For example, I could get it solved by using element[0].getElementsByClassName('scroll-rangeb') :

angular.module('app', [])
  .directive('bob', function() {
    return {
      restrict: 'A',
      transclude: true,
      template: `
          <div style="background-color: #333">
            <input type="range" value="0" class="scroll-rangeb">
            <div
              class="photo-containerb"
              style="display: flex; overflow-x: scroll; flex-direction: row; align-items: center; height: 90%;"
              ng-transclude>
            </div>
          </div>`,
      link: function(scope, $element, attrs) {
        var
          element = $element[0],
          scroll = element.getElementsByClassName("scroll-rangeb")[0],
          panel = element.getElementsByClassName("photo-containerb")[0];

        scroll.oninput = function() {
          var total = panel.scrollWidth - panel.offsetWidth;
          var percentage = total * (this.value / 100);

          panel.scrollLeft = percentage;
        }
      }
    };
  });
img {
  border-radius: 50%;
}

.box {
  display: block;
  width: 50px;
  height: 50px;
  min-width: 50px;
  margin: 10px;
}
<div ng-app="app">
  <div bob>
    <img class="box" ng-repeat="img in [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==">
  </div>
  <div bob>
    <img class="box" ng-repeat="img in [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==">
  </div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>

Upvotes: 1

Related Questions