使用相同的指令修改元素

时间:2016-10-14 15:11:19

标签: angularjs

我在容器中有几个元素。其中一行中有两个图标:放大和缩小。单击“放大”时,我希望所有行的宽度增长。

<div id="events">
    <year>year 1</year>
    <year>year 2</year>
    <year>year 3</year>
    <year>year 4</year>

    <div id="scaling">
        <md-icon aria-label="Zoom In" class="material-icons" ng-click="zoomIn()">zoom_in</md-icon>
        <md-icon aria-label="Zoom Out" class="material-icons" ng-click="zoomOut()">zoom_out</md-icon>
    </div>
</div>

我有一年的指令:

angular.module("app").directive("year", ['$rootScope', function ($rootScope) {
    return {
        link: function($scope, element, attr) {

            var events = element;

            $scope.zoomIn = function(ev) {

                console.log('zoomin');
                $scope.zoom = $scope.zoom + $scope.scale;

                if($scope.zoom < 100) { $scope.zoom = 100; }

                events.html($scope.zoom);

                events.css({
                    'width': $scope.zoom + '%'
                });
            }

            $scope.zoomOut = function(ev) {
                $scope.zoom = $scope.zoom - $scope.scale;

                if($scope.zoom < 100) { $scope.zoom = 100; }

                events.css({
                    'width': $scope.zoom + '%'
                });
            }
        }
    }
}]);

但宽度仅适用于去年的元素。这是为什么?

2 个答案:

答案 0 :(得分:1)

您每次都会覆盖范围。因此,year指令的每个实例都会在每次实例化时隐藏zoomInzoomOut方法。

通常,您可以通过在指令定义对象中使用new或isolate作用域来解决此问题:

//new scope
{
  scope: true
}

//isolate scope
{
  scope: {}
}

但是,由于您希望绑定点击处理程序外部您的个人year指令,因此您必须执行其他操作。

更好的解决方案是传递属性并简单地回应他们的更改:

return {
   scope: {
      zoom: '='
   },
   link: function(scope, elem, attrs){

      scope.$watch('zoom', function(){
         //Do something with 'scope.zoom'
      });

   }
};

现在,您的外部zoomInzoomOut函数只能修改父作用域上的某些zoom属性,您可以将year组件绑定到该属性。

<year zoom="myZoomNumber"></year>

仅为后代,这是一个工作片段。

function EventsController() {
  var $this = this;

  var zoom = 1;

  $this.zoom = zoom;

  $this.zoomIn = function() {
    zoom *= 1.1;

    $this.zoom = zoom;

    console.log({
      name: 'zoomIn',
      value: zoom
    });
  };

  $this.zoomOut = function() {
    zoom *= 0.9;

    $this.zoom = zoom;

    console.log({
      name: 'zoomOut',
      value: zoom
    });
  };
}

function YearDirective() {
  return {
    restrict: 'E',
    template: '<h1 ng-transclude></h1>',
    transclude: true,
    scope: {
      zoom: '='
    },
    link: function(scope, elem, attr) {
      var target = elem.find('h1')[0];

      scope.$watch('zoom', function() {
        var scaleStr = "scale(" + scope.zoom + "," + scope.zoom + ")";

        console.log({
          elem: target,
          transform: scaleStr
        });

        target.style.transform = scaleStr;
        target.style.transformOrigin = 'left';
      });
    }
  };
}

var mod = angular.module('my-app', []);

mod
  .controller('eventsCtrl', EventsController)
  .directive('year', YearDirective);
.scaling{
 z-index:1000;
 position:fixed;
 top:10px;
 left:10px;
}

.behind{
  margin-top:50px;
  z-index:-1;
  }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="my-app" ng-controller="eventsCtrl as $ctrl">

  <div class="scaling">
    <button type="button" aria-label="Zoom In" ng-click="$ctrl.zoomIn()">zoom_in</button>
    <button type="button" aria-label="Zoom Out" ng-click="$ctrl.zoomOut()">zoom_out</button>
  </div>
  <div class="behind">
    <year zoom="$ctrl.zoom">year 1</year>
    <year zoom="$ctrl.zoom">year 2</year>
    <year zoom="$ctrl.zoom">year 3</year>
    <year zoom="$ctrl.zoom">year 4</year>
  </div>

</div>

答案 1 :(得分:0)

events.css过度使用,因此只适用于最后一个元素。

events.css({
  'width': $scope.zoom + '%'
}).bind(this);

您必须bind it to current scope.