wake-up-neo.com

AngularJS - bindet an die Größe der Direktive

Wie kann ich benachrichtigt werden, wenn die Größe einer Richtlinie geändert wird? Ich habe es versucht 

element[0].onresize = function() {
            console.log(element[0].offsetWidth + " " + element[0].offsetHeight);
        }

aber es ist nicht die Funktion aufrufen

(function() {
'use strict';

// Define the directive on the module.
// Inject the dependencies. 
// Point to the directive definition function.
angular.module('app').directive('nvLayout', ['$window', '$compile', layoutDirective]);

function layoutDirective($window, $compile) {
    // Usage:
    // 
    // Creates:
    // 
    var directive = {
        link: link,
        restrict: 'EA',
        scope: {
            layoutEntries: "=",
            selected: "&onSelected"
        },
        template: "<div></div>",
        controller: controller
    };
    return directive;

    function link(scope, element, attrs) {
        var elementCol = [];

        var onSelectedHandler = scope.selected();

        element.on("resize", function () {
            console.log("resized.");
        });

        $(window).on("resize",scope.sizeNotifier);

        scope.$on("$destroy", function () {
            $(window).off("resize", $scope.sizeNotifier);
        });

        scope.sizeNotifier = function() {
            alert("windows is being resized...");
        };

        scope.onselected = function(id) {
            onSelectedHandler(id);
        };



        scope.$watch(function () {
            return scope.layoutEntries.length;
        },
        function (value) {
            //layout was changed
            activateLayout(scope.layoutEntries);
        });

        function activateLayout(layoutEntries) {


            for (var i = 0; i < layoutEntries.length; i++) {

                if (elementCol[layoutEntries[i].id]) {
                    continue;
                }
                var div = "<nv-single-layout-entry id=slot" + layoutEntries[i].id + " on-selected='onselected' style=\"position:absolute;";
                div = div + "top:" + layoutEntries[i].position.top + "%;";
                div = div + "left:" + layoutEntries[i].position.left + "%;";
                div = div + "height:" + layoutEntries[i].size.height + "%;";
                div = div + "width:" + layoutEntries[i].size.width + "%;";
                div = div + "\"></nv-single-layout-entry>";

                var el = $compile(div)(scope);
                element.append(el);
                elementCol[layoutEntries[i].id] = 1;
            }


        };
    }

    function controller($scope, $element) {

    }
}

      })();
22
li-raz

Verwenden Sie scope. $ Watch mit einer benutzerdefinierten Überwachungsfunktion:

scope.$watch(
  function () {
    return [element[0].offsetWidth, element[0].offsetHeight].join('x');
  },
  function (value) {
    console.log('directive got resized:', value.split('x'));
  }
)
15
epegzz

Normalerweise möchten Sie die Eigenschaften offsetWidth und offsetHeight des Elements überwachen. Mit neueren Versionen von AngularJS können Sie $scope.$watchGroup in Ihrer Link-Funktion verwenden:

app.directive('myDirective', [function() {

    function link($scope, element) {
        var container = element[0];

        $scope.$watchGroup([
            function() { return container.offsetWidth; },
            function() { return container.offsetHeight; }
        ],  function(values) {
              // Handle resize event ...
        });
    }

    // Return directive definition ...

}]);

Möglicherweise stellen Sie jedoch fest, dass Updates recht langsam sind, wenn Sie die Elementeigenschaften auf diese Weise direkt betrachten.

Um Ihre Direktive ansprechbarer zu machen, können Sie die Aktualisierungsrate mithilfe von $interval verringern. Hier ein Beispiel für einen wiederverwendbaren Dienst zum Überwachen von Elementgrößen mit einer konfigurierbaren Millisekundenrate:

app.factory('sizeWatcher', ['$interval', function($interval) {
    return function (element, rate) {
        var self = this;
        (self.update = function() { self.dimensions = [element.offsetWidth, element.offsetHeight]; })();
        self.monitor = $interval(self.update, rate);
        self.group = [function() { return self.dimensions[0]; }, function() { return self.dimensions[1]; }];
        self.cancel = function() { $interval.cancel(self.monitor); };
    };
}]);

Eine Anweisung, die einen solchen Dienst verwendet, würde in etwa so aussehen:

app.directive('myDirective', ['sizeWatcher', function(sizeWatcher) {

    function link($scope, element) {
        var container = element[0],
            watcher = new sizeWatcher(container, 200);

        $scope.$watchGroup(watcher.group, function(values) {
            // Handle resize event ...
        });

        $scope.$on('$destroy', watcher.cancel);
    }

    // Return directive definition ...

}]);

Beachten Sie den Aufruf von watcher.cancel() im $scope.$destroy-Ereignishandler. Dadurch wird sichergestellt, dass die $interval-Instanz gelöscht wird, wenn sie nicht mehr benötigt wird.

Ein JSFiddle-Beispiel finden Sie hier .

13
SimonSparks

Hier ein Beispielcode für das, was Sie tun müssen: 

APP.directive('nvLayout', function ($window) {
  return {
    template: "<div></div>",
    restrict: 'EA',
    link: function postLink(scope, element, attrs) {

      scope.onResizeFunction = function() {
        scope.windowHeight = $window.innerHeight;
        scope.windowWidth = $window.innerWidth;

        console.log(scope.windowHeight+"-"+scope.windowWidth)
      };

      // Call to the function when the page is first loaded
      scope.onResizeFunction();

      angular.element($window).bind('resize', function() {
        scope.onResizeFunction();
        scope.$apply();
      });
    }
  };
});
7
Eliel Haouzi

Die einzige Möglichkeit, mit Hilfe von $ watch Größen-/Positionsänderungen an einem Element zu erkennen, besteht darin, dass Sie Ihren Gültigkeitsbereich ständig mit etwas wie $ intervall oder $ timeout aktualisieren. Während dies möglich ist, kann dies zu einem teuren Vorgang werden und Ihre App wirklich verlangsamen.

Eine Möglichkeit, eine Änderung an einem Element festzustellen, ist der Aufruf von requestAnimationFrame.

var previousPosition = element[0].getBoundingClientRect();

onFrame();

function onFrame() {
  var currentPosition = element[0].getBoundingClientRect();

  if (!angular.equals(previousPosition, currentPosition)) {
    resiszeNotifier();
  }

  previousPosition = currentPosition;
  requestAnimationFrame(onFrame);
}

function resiszeNotifier() {
  // Notify...
}

Hier ist ein Plunk, der das demonstriert. Solange Sie die Box bewegen, bleibt sie rot.

http://plnkr.co/edit/qiMJaeipE9DgFsYd0sfr?p=preview

2
Blake Bowen

Hier ist meine Einstellung zu dieser Anweisung (mit Webpack als Bundler):

module.exports = (ngModule) ->

  ngModule.directive 'onResize', ['Callback', (Callback) ->
    restrict: 'A'
    scope:
      onResize: '@'
      onResizeDebounce: '@'
    link: (scope, element) ->
      container = element[0]
      eventName = scope.onResize || 'onResize'
      delay = scope.onResizeDebounce || 1000
      scope.$watchGroup [
        -> container.offsetWidth ,
        -> container.offsetHeight
      ], _.debounce (values) ->
        Callback.event(eventName, values)
      , delay
  ]
0
Kamil

Eine kleine Abweichung von Eliels Antwort funktionierte für mich. In der Direktive.js:

      $scope.onResizeFunction = function() {
      };

      // Call to the function when the page is first loaded
      $scope.onResizeFunction();

      angular.element($(window)).bind('resize', function() {
        $scope.onResizeFunction();
        $scope.$apply();
      });

Ich rufe

    $(window).resize();

aus meiner app.js. Das D3-Diagramm der Direktive ändert jetzt die Größe, um den Container zu füllen.

0
Matt Bearson