【问题标题】:Angular Directive only works on one element at a timeAngular Directive 一次只适用于一个元素
【发布时间】:2017-09-17 11:52:45
【问题描述】:

我有以下角度指令。它使用范围滑块滚动项目的水平 div。如果仅应用于一行,它就可以工作。但如果应用于多个......什么也不会发生。嵌入有效,但函数从不运行,也没有给出错误。我该怎么做才能使其更具角度通用性并适用于多个元素?这是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;
                }
            }
        };
    });

【问题讨论】:

  • 在黑暗中拍摄,但您是否尝试过隔离范围?
  • @zero298 无法使用隔离范围。立即创建重现。
  • 您为什么希望这可以处理多个项目?您正在手动引用单个 id!这是一种非常“不合时宜”的方式。
  • @DavidL 我对 Angular 和 jQuery 背景比较陌生。仍然不了解“Angular”方式。我还用 .getElementsByClassName 切换了 .getElementById,但仍然没有成功。
  • 多个组件尝试使用相同的 ID,这是行不通的。如果需要爬取 DOM,至少只在单个组件的元素内进行爬取。 (通常在 Angular 中,你不想爬取 DOM,如果组件需要访问特定的子节点,你可以在模板中进行,或者在组件实例化时绑定它们。)

标签: javascript angularjs angular-directive


【解决方案1】:

#scroll-rangeb 是一个独特的元素(理论上),如果您在每个指令上覆盖oninput,它显然不会起作用,它只会保留第一个找到的元素。无论如何,您根本不能使用具有相同 id 的多个组件。尝试从链接函数给出的元素参数中找到它,而不是使用类或其他东西。

例如,我可以使用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>

【讨论】:

  • 谢谢!我能够得到CodePen 与您的答案一起工作。但是由于某种原因,您的示例不起作用……至少对我而言。但这正是我想要做的,我不知道你可以这样使用element
  • @Auzy sn-p 正在为 firefox 工作,我不确定为什么它对你不起作用,或者你是否收到任何错误。无论如何,它似乎对你有用。
  • 是的,可以确认在 Firefox 中工作。我正在使用 Chrome ......很奇怪。没有错误,只是没有运行。可能只是考虑次要的 CSS 规则。用 min-width 替换显示内联块似乎可以在 chrome 中为我修复它。愚蠢的浏览器哈哈。干杯!
猜你喜欢
  • 2021-10-27
  • 2014-11-28
  • 1970-01-01
  • 2014-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多