2014-01-16 5 views
21

지시문 크기를 조정할 때 어떻게 알림을받을 수 있습니까? 내가AngularJS - 지시문 크기 변경에 바인딩

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

을 시도했지만 그 다음은 기능

(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) { 

    } 
} 

     })(); 
+0

그러나 그것은 나에게 어렵다. 코드의 JQuery 종속성을 제거했으며 여기에서 확인할 수 있습니다. http://jsfiddle.net/U3pVM/2669/ –

+0

지시문의 요소 크기를 조정할 때 알림을 받으려고합니다. 전체 페이지에서들을 수 있지만 elemnt가 지시어를 움직일 때를 알고 싶습니다. –

+0

@ li-raz : [내 답변] (http://stackoverflow.com/a/23031644/434989) 정확히 다음과 같이 수행합니다 :-) – epegzz

답변

7

당신이해야 할 일의 샘플 코드를 호출하지 :

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(); 
     }); 
    } 
    }; 
}); 
+15

지시어 만 크기를 조정할 수 있지만 창 자체는 조정할 수 없습니다. – epegzz

+0

바인드가 나를 위해 일하고있다 ... 내가 전화를 걸 필요가 없다고 생각한다. –

14

사용 scope.$watch을 사용자 정의 시계 기능을 :

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

나는 이것을 시도했지만 일반적으로 나에게 오래된 값을 보여준다. 버튼을 사용하여 숨기거나 표시 할 수있는 사이드 바를 가지고 있습니다. 클릭하면 다이제스트주기가 발생하고 시계 기능이 요소의 크기가 변경되지 않았 음을 알려주고 요소의 크기가 조정되어 다음주기에 선택됩니다. , 이는 결함을 일으킨다. 어떤 아이디어? –

+1

@HernanRajchert (및 다른 향후 독자) _ [clientHeight] (https://developer.mozilla.org/en-US/docs/Web/API/Element.clientHeight)는 CSS 높이 + CSS 패딩 - 가로 스크롤 막대 높이 (있는 경우) ._ 원하는 것은 [.offsetHeight] (https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement.offsetHeight)입니다. 'element [0] .offsetHeight' (그리고 너비)가 작동하는 것을보아야합니다. –

+0

@JordanCarroll 나를 위해 clientHeight 대신 offsetHeight를 사용하여 문제가 해결되지 않았습니다. – nardnob

2

$ watch를 사용하여 요소의 크기/위치 변경을 감지 할 수있는 유일한 방법은 $ interval 또는 $ timeout과 같은 것을 사용하여 범위를 지속적으로 업데이트하는 경우입니다. 가능하면 값 비싼 작업이 될 수 있으며 앱을 정말로 느려지 게 만듭니다.

요소 변경을 감지 할 수있는 방법 중 하나는 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... 
} 

다음은 이것을 설명하는 플 런크입니다. 상자를 움직이면 빨간색으로 유지됩니다.

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

12

당신은 일반적으로 요소의 offsetWidthoffsetHeight 속성을보고 싶어한다. AngularJS와의 최신 버전으로, 당신은 당신의 연결 기능에 $scope.$watchGroup를 사용할 수 있습니다

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 ... 

}]); 

그러나이 방식으로 직접 요소의 속성을 볼 때 업데이트가 매우 느린 것을 알 수 있습니다.

지침의 응답 속도를 향상 시키려면 $interval을 사용하여 새로 고침 빈도를 조정할 수 있습니다. 다음은 구성 밀리 초 속도로 요소의 크기를 시청 재사용 가능한 서비스의 예는 다음과 같습니다

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); }; 
    }; 
}]); 

같은 것을 보일 것 같은 서비스를 사용하는 지침 :

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 ... 

}]); 

주를에 watcher.cancel()에 대한 호출 $scope.$destroy 이벤트 핸들러; 이렇게하면 더 이상 필요하지 않을 때 $interval 인스턴스가 삭제됩니다.

JSFiddle 예제는 here입니다.

+3

이 방법을 사용하고자하는 사람은'$ interval (self.update, rate);'를'$ interval (self.update, rate, 0, false);'로 대체하는 것을 고려한다. . 그렇지 않으면 각 인터벌 콜백 함수 호출에서 범위에 대한 다이제스트가 호출됩니다. 이것을 $ scope로 검사 할 수있다. $ watch (function() {console.log ("invalidated");});' –

0

엘리엘의 대답에 약간의 변형이 작용했습니다. directive.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(); 
     }); 

내 app.js. 내에서

$(window).resize(); 

전화 지시문의 d3 차트가 이제 컨테이너를 채우기 위해 크기가 조정됩니다.

0

여기 (번 들러로 Webpack를 사용하여)이 지침에 내 걸릴 수 있습니다 : 나는 코드의 목적을 이해 시도

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 
    ]