AngularJS가로드를 마쳤을 때 이벤트 보내기


114

모든 지시문이 컴파일 / 링크를 완료했을 때 페이지 로딩 / 부트 스트랩의 완료를 감지하는 가장 좋은 방법이 무엇인지 궁금했습니다.

이미 이벤트가 있습니까? 부트 스트랩 기능을 오버로드해야합니까?

답변:


204

직감 : ngCloak 지시문이 어떻게 작동하는지 살펴 보지 않겠습니까? 분명히 ngCloak 지시문은로드 된 후 콘텐츠를 표시하도록 관리합니다. ngCloak을 보면 정확한 답을 얻을 수있을 것입니다 ...

1 시간 후 편집 : 좋아, 글쎄, ngCloak보았는데 정말 짧습니다. 이것이 분명히 의미하는 것은 {{template}} 표현식이 평가 될 때까지 컴파일 함수가 실행되지 않는다는 것입니다 (즉,로드 한 템플릿). 따라서 ngCloak 지시어의 멋진 기능이 있습니다.

내 교육적인 추측은 ngCloak과 동일한 단순성으로 지시문을 만든 다음 컴파일 함수에서 원하는 것을 수행하는 것입니다. :) 앱의 루트 요소에 지시문을 배치하십시오. myOnload와 같은 지시문을 호출하여 my-onload 속성으로 사용할 수 있습니다. 컴파일 함수는 템플릿이 컴파일되면 실행됩니다 (표현식 평가 및 하위 템플릿로드).

편집, 23 시간 후 : 좋아, 그래서 나는 약간의 조사를했고, 나 자신의 질문도했다 . 제가 물은 질문은이 질문과 간접적으로 관련이 있었지만 우연히이 질문을 해결하는 답을 찾았습니다.

대답은 간단한 지시문을 만들고 지시문의 링크 함수에 코드를 넣을 수 있다는 것입니다.이 함수는 요소가 준비 /로드 될 때 실행됩니다 (대부분의 사용 사례에서 아래 설명). 를 기반으로 컴파일 및 링크 기능이 실행되는 순서의 조쉬의 설명 ,

이 마크 업이있는 경우 :

<div directive1>
  <div directive2>
    <!-- ... -->
  </div>
</div>

그런 다음 AngularJS는 특정 순서로 지시문 함수를 실행하여 지시문을 만듭니다.

directive1: compile
  directive2: compile
directive1: controller
directive1: pre-link
  directive2: controller
  directive2: pre-link
  directive2: post-link
directive1: post-link

기본적으로 직선 "링크"함수는 사후 링크이므로 외부 지시문 1의 링크 함수는 내부 지시문 2의 링크 함수가 실행될 때까지 실행되지 않습니다. 이것이 포스트 링크에서 DOM 조작을 수행하는 것이 안전하다고 말하는 이유입니다. 따라서 원래 질문에 대해서는 위에서 언급했듯이 동적으로 삽입 된 내용을 컴파일해야하지만 외부 지시문의 링크 함수에서 자식 지시문의 내부 html에 액세스하는 데 문제가 없어야합니다.

이것으로부터 우리는 모든 것이 준비 / 컴파일 / 링크 /로드되었을 때 우리 코드를 실행하기위한 지시문을 만들 수 있다는 결론을 내릴 수 있습니다.

    app.directive('ngElementReady', [function() {
        return {
            priority: -1000, // a low number so this directive loads after all other directives have loaded. 
            restrict: "A", // attribute only
            link: function($scope, $element, $attributes) {
                console.log(" -- Element ready!");
                // do what you want here.
            }
        };
    }]);

이제 할 수있는 일은 앱의 루트 요소에 ngElementReady 지시문을 배치하는 것입니다. 그러면는 console.log로드 될 때 실행됩니다.

<body data-ng-app="MyApp" data-ng-element-ready="">
   ...
   ...
</body>

간단합니다! 간단한 지시문을 작성하고 사용하십시오. ;)

다음을 추가하여 표현식 (예 : 함수)을 실행할 수 있도록 추가로 사용자 정의 할 수 있습니다 $scope.$eval($attributes.ngElementReady);.

    app.directive('ngElementReady', [function() {
        return {
            priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
            restrict: "A",
            link: function($scope, $element, $attributes) {
                $scope.$eval($attributes.ngElementReady); // execute the expression in the attribute.
            }
        };
    }]);

그런 다음 모든 요소에서 사용할 수 있습니다.

<body data-ng-app="MyApp" data-ng-controller="BodyCtrl" data-ng-element-ready="bodyIsReady()">
    ...
    <div data-ng-element-ready="divIsReady()">...<div>
</body>

요소가있는 범위 (컨트롤러에서)에 함수 (예 : bodyIsReady 및 divIsReady)가 정의되어 있는지 확인하십시오.

주의 사항 : 대부분의 경우에 효과가 있다고 말했습니다 . ngRepeat 및 ngIf와 같은 특정 지시문을 사용할 때는주의하십시오. 그들은 자신의 범위를 만들고 지시문이 실행되지 않을 수 있습니다. 예를 들어 ngIf가있는 요소에 새 ngElementReady 지시문을 배치하고 ngIf의 조건이 false로 평가되면 ngElementReady 지시문이로드되지 않습니다. 또는 예를 들어 ngInclude 지시문이있는 요소에 새 ngElementReady 지시문을 배치하면 ngInclude에 대한 템플릿이 없으면 지시문이로드되지 않습니다. 지시문을 모두 동일한 요소에 배치하는 대신 중첩하여 이러한 문제 중 일부를 해결할 수 있습니다. 예를 들어 다음을 수행합니다.

<div data-ng-element-ready="divIsReady()">
    <div data-ng-include="non-existent-template.html"></div>
<div>

대신 :

<div data-ng-element-ready="divIsReady()" data-ng-include="non-existent-template.html"></div>

ngElementReady 지시문은 후자의 예에서 컴파일되지만 링크 함수는 실행되지 않습니다. 참고 : 지시문은 항상 컴파일되지만 위와 같은 특정 시나리오에 따라 링크 함수가 항상 실행되는 것은 아닙니다.

몇 분 후 수정 :

아, 그리고 질문에 완전히 답하기 위해 속성 에서 실행되는 표현식 또는 함수에서 이제 $emit또는 $broadcast이벤트 를 사용할 수 있습니다 ng-element-ready. :) 예 :

<div data-ng-element-ready="$emit('someEvent')">
    ...
<div>

몇 분 후에 수정 :

@satchmorun의 답변도 작동하지만 초기로드에만 적용됩니다. 여기에 링크 함수 등을 포함하여 실행되는 순서를 설명 하는 매우 유용한 SO 질문app.run있습니다. 따라서 사용 사례에 따라 app.run좋을 수도 있지만 특정 요소에는 적합하지 않을 수 있습니다.이 경우 링크 기능이 더 좋습니다.

수정, 5 개월 후, 10 월 17 일 8:11 PST :

비동기 적으로로드 된 부분은 작동하지 않습니다. 부분에 부기를 추가해야합니다 (예 : 한 가지 방법은 각 부분이 콘텐츠로드가 완료되는시기를 추적 한 다음 이벤트를 생성하여 부모 범위가 몇 개의 부분이로드되었는지 계산하고 마지막으로 필요한 작업을 수행 할 수 있도록하는 것입니다. 모든 부분이로드 된 후 수행).

수정, 10 월 23 일 오후 10시 52 분 PST :

이미지가로드 될 때 일부 코드를 실행하기위한 간단한 지시문을 만들었습니다.

/*
 * This img directive makes it so that if you put a loaded="" attribute on any
 * img element in your app, the expression of that attribute will be evaluated
 * after the images has finished loading. Use this to, for example, remove
 * loading animations after images have finished loading.
 */
  app.directive('img', function() {
    return {
      restrict: 'E',
      link: function($scope, $element, $attributes) {
        $element.bind('load', function() {
          if ($attributes.loaded) {
            $scope.$eval($attributes.loaded);
          }
        });
      }
    };
  });

수정, 10 월 24 일 오전 12시 48 분 PST :

원래 ngElementReady지시문을 개선 하고 이름을 whenReady.

/*
 * The whenReady directive allows you to execute the content of a when-ready
 * attribute after the element is ready (i.e. done loading all sub directives and DOM
 * content except for things that load asynchronously like partials and images).
 *
 * Execute multiple expressions by delimiting them with a semi-colon. If there
 * is more than one expression, and the last expression evaluates to true, then
 * all expressions prior will be evaluated after all text nodes in the element
 * have been interpolated (i.e. {{placeholders}} replaced with actual values). 
 *
 * Caveats: if other directives exists on the same element as this directive
 * and destroy the element thus preventing other directives from loading, using
 * this directive won't work. The optimal way to use this is to put this
 * directive on an outer element.
 */
app.directive('whenReady', ['$interpolate', function($interpolate) {
  return {
    restrict: 'A',
    priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
    link: function($scope, $element, $attributes) {
      var expressions = $attributes.whenReady.split(';');
      var waitForInterpolation = false;

      function evalExpressions(expressions) {
        expressions.forEach(function(expression) {
          $scope.$eval(expression);
        });
      }

      if ($attributes.whenReady.trim().length == 0) { return; }

      if (expressions.length > 1) {
        if ($scope.$eval(expressions.pop())) {
          waitForInterpolation = true;
        }
      }

      if (waitForInterpolation) {
        requestAnimationFrame(function checkIfInterpolated() {
          if ($element.text().indexOf($interpolate.startSymbol()) >= 0) { // if the text still has {{placeholders}}
            requestAnimationFrame(checkIfInterpolated);
          }
          else {
            evalExpressions(expressions);
          }
        });
      }
      else {
        evalExpressions(expressions);
      }
    }
  }
}]);

예를 들어 다음과 같이 사용 someFunction하여 요소가로드되고 {{placeholders}}아직 교체되지 않은 경우 실행합니다.

<div when-ready="someFunction()">
  <span ng-repeat="item in items">{{item.property}}</span>
</div>

someFunction모든 item.property자리 표시자가 교체 되기 전에 호출됩니다 .

원하는만큼 식 true{{placeholders}}평가하고 다음과 같이 평가 되기를 기다리는 마지막 식 을 만듭니다 .

<div when-ready="someFunction(); anotherFunction(); true">
  <span ng-repeat="item in items">{{item.property}}</span>
</div>

someFunction그리고 anotherFunction이후에 발사 될 것이다 {{placeholders}}대체되었습니다.

이는 요소가 처음로드 될 때만 작동하며 향후 변경 사항에서는 작동하지 않습니다. $digest자리 표시자를 처음 교체 한 후에도 계속 발생 하면 원하는대로 작동하지 않을 수 있습니다 ($ digest는 데이터 변경이 중지 될 때까지 최대 10 번 발생할 수 있음). 대부분의 사용 사례에 적합합니다.

수정, 10 월 31 일 오후 7:26 PST :

좋아, 이것은 아마도 나의 마지막이자 마지막 업데이트 일 것이다. 이것은 아마도 99.999 개의 사용 사례에서 작동 할 것입니다.

/*
 * The whenReady directive allows you to execute the content of a when-ready
 * attribute after the element is ready (i.e. when it's done loading all sub directives and DOM
 * content). See: /programming/14968690/sending-event-when-angular-js-finished-loading
 *
 * Execute multiple expressions in the when-ready attribute by delimiting them
 * with a semi-colon. when-ready="doThis(); doThat()"
 *
 * Optional: If the value of a wait-for-interpolation attribute on the
 * element evaluates to true, then the expressions in when-ready will be
 * evaluated after all text nodes in the element have been interpolated (i.e.
 * {{placeholders}} have been replaced with actual values).
 *
 * Optional: Use a ready-check attribute to write an expression that
 * specifies what condition is true at any given moment in time when the
 * element is ready. The expression will be evaluated repeatedly until the
 * condition is finally true. The expression is executed with
 * requestAnimationFrame so that it fires at a moment when it is least likely
 * to block rendering of the page.
 *
 * If wait-for-interpolation and ready-check are both supplied, then the
 * when-ready expressions will fire after interpolation is done *and* after
 * the ready-check condition evaluates to true.
 *
 * Caveats: if other directives exists on the same element as this directive
 * and destroy the element thus preventing other directives from loading, using
 * this directive won't work. The optimal way to use this is to put this
 * directive on an outer element.
 */
app.directive('whenReady', ['$interpolate', function($interpolate) {
  return {
    restrict: 'A',
    priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
    link: function($scope, $element, $attributes) {
      var expressions = $attributes.whenReady.split(';');
      var waitForInterpolation = false;
      var hasReadyCheckExpression = false;

      function evalExpressions(expressions) {
        expressions.forEach(function(expression) {
          $scope.$eval(expression);
        });
      }

      if ($attributes.whenReady.trim().length === 0) { return; }

    if ($attributes.waitForInterpolation && $scope.$eval($attributes.waitForInterpolation)) {
        waitForInterpolation = true;
    }

      if ($attributes.readyCheck) {
        hasReadyCheckExpression = true;
      }

      if (waitForInterpolation || hasReadyCheckExpression) {
        requestAnimationFrame(function checkIfReady() {
          var isInterpolated = false;
          var isReadyCheckTrue = false;

          if (waitForInterpolation && $element.text().indexOf($interpolate.startSymbol()) >= 0) { // if the text still has {{placeholders}}
            isInterpolated = false;
          }
          else {
            isInterpolated = true;
          }

          if (hasReadyCheckExpression && !$scope.$eval($attributes.readyCheck)) { // if the ready check expression returns false
            isReadyCheckTrue = false;
          }
          else {
            isReadyCheckTrue = true;
          }

          if (isInterpolated && isReadyCheckTrue) { evalExpressions(expressions); }
          else { requestAnimationFrame(checkIfReady); }

        });
      }
      else {
        evalExpressions(expressions);
      }
    }
  };
}]);

이렇게 사용하세요

<div when-ready="isReady()" ready-check="checkIfReady()" wait-for-interpolation="true">
   isReady will fire when this {{placeholder}} has been evaluated
   and when checkIfReady finally returns true. checkIfReady might
   contain code like `$('.some-element').length`.
</div>

물론 최적화 할 수는 있지만 그대로 두겠습니다. requestAnimationFrame 이 좋습니다.


3
모든 "data-"접두사로 인해 정말 짜증납니다. 나는 그것들을 직접 사용하지 않는 것이 기쁩니다.
stolsvik 2014-06-09

1
@stolsvik heh, 예, 가장 현대적인 브라우저에서는 필요하지 않습니다.
trusktr

49
이 답변에 투입된 시간과 노력에 대해 투표 할 가치가 있습니다. 잘 하셨어요!
GordyD

8
좋은 대답이지만 모든 "편집"줄을 제거하고 대답을 약간 재구성하는 것이 좋습니다. 수정 내역은 답변 하단의 "수정 됨 ..."링크를 통해 제공되며 읽는 동안주의가 산만 해집니다.
user247702 2011 년

2
소스 코드가 정말 도움이 될 것입니다. 그리고 npm에 공개 할 수 있다면 완벽 할 것입니다. 정말 좋은 대답, 정말 멋지게 설명했습니다. 이것에 대한 노력의 양에 +1입니다.
tfrascaroli

38

에 대한 문서angular.Module 에는 run함수를 설명하는 항목이 있습니다.

이 메서드를 사용하여 인젝터가 모든 모듈로드를 완료 할 때 수행해야하는 작업을 등록합니다.

따라서 앱에 해당하는 모듈이있는 경우 :

var app = angular.module('app', [/* module dependencies */]);

모듈이로드 된 후 다음을 실행할 수 있습니다.

app.run(function() {
  // Do post-load initialization stuff here
});

편집 : 구조에 수동 초기화

그래서 runDOM이 준비되고 연결되었을 때는 호출되지 않는다는 지적 이있었습니다. 에서 $injector참조하는 모듈 ng-app의가 DOM 컴파일 단계와는 별개로 모든 종속성을로드 하면 호출됩니다 .

수동 초기화를 다시 살펴 보았는데 이것이 트릭을 수행해야하는 것 같습니다.

설명하기 위해 바이올린을 만들었습니다 .

HTML은 간단합니다.

<html>
    <body>
        <test-directive>This is a test</test-directive>
    </body>
</html>

의 부족을합니다 ng-app. 그리고 DOM 조작을 수행하는 지시문이 있으므로 사물의 순서와 타이밍을 확인할 수 있습니다.

평소와 같이 모듈이 생성됩니다.

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

그리고 다음은 지시문입니다.

app.directive('testDirective', function() {
    return {
        restrict: 'E',
        template: '<div class="test-directive"><h1><div ng-transclude></div></h1></div>',
        replace: true,
        transclude: true,
        compile: function() {
            console.log("Compiling test-directive");
            return {
                pre: function() { console.log("Prelink"); },
                post: function() { console.log("Postlink"); }
            };
        }
    };
});

test-directive태그를 divof class 로 바꾸고 test-directive내용을 h1.

사전 및 사후 링크 함수를 모두 반환하는 컴파일 함수를 추가하여 이러한 작업이 언제 실행되는지 확인할 수 있습니다.

나머지 코드는 다음과 같습니다.

// The bootstrapping process

var body = document.getElementsByTagName('body')[0];

// Check that our directive hasn't been compiled

function howmany(classname) {
    return document.getElementsByClassName(classname).length;
}

어떤 작업을 수행하기 전에 test-directiveDOM에 클래스가 있는 요소 가 없어야하며 작업이 완료된 후에는 1이 있어야합니다.

console.log('before (should be 0):', howmany('test-directive'));

angular.element(document).ready(function() {
    // Bootstrap the body, which loades the specified modules
    // and compiled the DOM.
    angular.bootstrap(body, ['app']);

    // Our app is loaded and the DOM is compiled
    console.log('after (should be 1):', howmany('test-directive'));
});

매우 간단합니다. 문서가 준비되면 angular.bootstrap앱의 루트 요소와 모듈 이름 배열을 사용하여 호출 합니다.

실제로 모듈에 함수를 연결runapp 하면 컴파일이 발생하기 전에 실행되는 것을 볼 수 있습니다.

바이올린을 실행하고 콘솔을 보면 다음이 표시됩니다.

before (should be 0): 0 
Compiling test-directive 
Prelink
Postlink
after (should be 1): 1 <--- success!

2
감사합니다 @satchmorun! 그러나 run ()은 연결 부분이 끝나기 전에 실행됩니다. 일부 console.logs로 확인했습니다.
Lior

자신 호기심 ... 나는 화재가 일부 jQuery를 DOM 플러그인을 구현하는 지침이되었다 run지시문 전에 화재 및 실행 화재, HTML은 모든이없는
charlietfl

@charlietfl-수동 부트 스트래핑에 대해 조금 파헤 쳤고 실제로 질문이 찾고있는 것을 얻는 매우 쉬운 방법입니다. 내 원래 답변에 꽤 긴 편집을 추가했습니다.
satchmorun 2013

5
$timeout( initMyPlugins,0)내 지시문 내에서 작업 을 사용하는 것을 발견했습니다. 필요한 모든 HTML이 거기에 있습니다
charlietfl

@satchmorun,이 후속 조치 참조 : stackoverflow.com/questions/14989161/…
Lior

16

Angular는 페이지로드가 완료되면 신호를 보내는 방법을 제공하지 않았습니다. 아마도 '완료'는 애플리케이션에 따라 달라 지기 때문일 수 있습니다 . 예를 들어 계층 적 부분 트리가있는 경우 하나는 다른 하나를로드합니다. "Finish"는 모두로드되었음을 의미합니다. 모든 프레임 워크는 코드를 분석하고 모든 것이 완료되었거나 여전히 기다려야한다는 것을 이해하는 데 어려움을 겪을 것입니다. 이를 위해서는 애플리케이션 별 로직을 제공하여이를 확인하고 결정해야합니다.


14

각도 초기화가 완료 될 때를 평가할 때 상대적으로 정확한 솔루션을 생각해 냈습니다.

지시문은 다음과 같습니다.

.directive('initialisation',['$rootScope',function($rootScope) {
            return {
                restrict: 'A',
                link: function($scope) {
                    var to;
                    var listener = $scope.$watch(function() {
                        clearTimeout(to);
                        to = setTimeout(function () {
                            console.log('initialised');
                            listener();
                            $rootScope.$broadcast('initialised');
                        }, 50);
                    });
                }
            };
        }]);

그런 다음 body요소에 속성으로 추가 한 다음$scope.$on('initialised', fn)

$ digest주기가 더 이상 없을 때 애플리케이션이 초기화된다고 가정하여 작동합니다. $ watch는 모든 다이제스트 사이클을 호출하므로 타이머가 시작됩니다 ($ timeout이 아닌 setTimeout이므로 새 다이제스트 사이클이 트리거되지 않음). 타임 아웃 내에 다이제스트주기가 발생하지 않으면 애플리케이션이 초기화 된 것으로 간주됩니다.

분명히 satchmoruns 솔루션만큼 정확하지는 않지만 (다이제스트주기가 시간 초과보다 오래 걸릴 수 있으므로) 내 솔루션은 관리하기 훨씬 쉽게 만드는 모듈을 추적 할 필요가 없습니다 (특히 대규모 프로젝트의 경우) ). 어쨌든 내 요구 사항에 충분히 정확한 것 같습니다. 도움이 되었기를 바랍니다.


탁월한 솔루션. 하나 또는 두 개의 압축 파일에있는 모든 코드가 매우 잘 작동하는 프로젝트의 경우.
merqlove 2014-09-08

1
이것은 환상적인 솔루션입니다. jquery에 많은 코드가 있고 코드를 단계별로 각도로 변환하려는 경우 이것은 완벽합니다.
Mangesh Pimpalkar 2014

11

Angular UI Router를 사용 하는 $viewContentLoaded경우 이벤트를 수신 할 수 있습니다 .

"$ viewContentLoaded- DOM이 렌더링 된 후 뷰가로드되면 시작됩니다 . 뷰의 '$ scope'가 이벤트를 내 보냅니다." - 링크

$scope.$on('$viewContentLoaded', 
function(event){ ... });

3
$ scope. $ watch ( '$ viewContentLoaded', function ()이 나를 위해 트릭을 만들었습니다
Louis XIV

2
'당신이되어야하는 것'에 대해 반대표를 받았습니다. 만약 내가 만약 당신이 Angular 대신 React를 사용한다면 (당신이해야만하는) ... "라고 말하면? 이 생태계 IMHO에서 갖는 태도는 그리 좋지 않습니다.
Valentin Waeselynck

@ValentinWaeselynck 당신이 절대적으로 옳습니다. 내 편견을 제거하기 위해 내 대답을 편집했습니다.
Jordan Skole

1
나를 위해 일했습니다! 감사합니다. 실제로 실행 함수에 추가 한 다음 $ scope를 $ rootScope로 변경했습니다.
JDavies

2
Angular University가 다른 답변에서 지적했듯이 $ viewContentLoaded는 원래 거기에 없었을 수도 있지만 이제는 기본 제공 ngRoute 공급자에서 정확히 동일한 방식으로 작동합니다. 이를 염두에두고 앞으로 많은 독자들이 찾고있는 빠르고 간단하며 읽기 쉬운 대답이라고 생각합니다.
Kevin Crumley

3

나는 JQuery로 각도의 DOM 조작을 관찰하고 내 앱에 대한 마무리를 설정했습니다 (내 앱 개요에 필요한 일종의 미리 정의되고 만족스러운 상황). 예를 들어 ng-repeater가 7 결과를 생성 할 것으로 기대합니다. 이를 위해 setInterval의 도움으로 관찰 함수를 설정합니다.

$(document).ready(function(){

  var interval = setInterval(function(){

  if($("article").size() == 7){
     myFunction();
     clearInterval(interval);
  }

  },50);

});

3
나는 이것을하지 않을 것이다. 간격을 사용하여 일어나는 일을 확인하는 것은 좋은 습관이 아니며 확장 할 수 없으며 일을 발생시키는 다른 방법이 있습니다. 타이머는 콘텐츠 나 결과가 준비되었을 때 "추측"하는 것이 아니라 특정 기간 후에 발생해야하는 구체적인 작업을 수행하기위한 것입니다.
dudewad

앵귤러 플랫폼에 대해 jquery 타이머를 사용하는 것은 비생산적이라는 것은 말할 필요도 없습니다. 앵귤러에는 타임 아웃 클래스가 있으므로이를 사용해야합니다. 그렇지 않으면 두 프레임 워크에 걸쳐 있고 매우 빠르게 혼란스러워집니다.
dudewad 2014

3

ngRoute 모듈을 사용하지 않는 경우 , 즉 $ viewContentLoaded 이벤트 가 없습니다 .

다른 지시문 방법을 사용할 수 있습니다.

    angular.module('someModule')
        .directive('someDirective', someDirective);

    someDirective.$inject = ['$rootScope', '$timeout']; //Inject services

    function someDirective($rootScope, $timeout){
        return {
            restrict: "A",
            priority: Number.MIN_SAFE_INTEGER, //Lowest priority
            link    : function(scope, element, attr){
                $timeout(
                    function(){
                        $rootScope.$emit("Some:event");
                    }
                );
            }
        };
    }

따라서 trusktr의 대답 에 따르면 우선 순위가 가장 낮습니다. 게다가 $ timeout 은 Angular가 콜백 실행 전에 전체 이벤트 루프를 실행하도록합니다.

$ rootScope 는 응용 프로그램의 모든 범위에 지시문을 배치하고 필요한 리스너에게만 알릴 수 있기 때문에 사용됩니다.

$ rootScope. $ emit은 모든 $ rootScope. $ on 리스너에 대해서만 이벤트를 발생시킵니다. 흥미로운 부분은 $ rootScope. $ 방송은 모든 $의 rootScope을 알려 것입니다. 물론 $ 범위로에 $. 청취자에 $ 소스


2

Angular 팀과이 Github 문제 에 따르면 :

이제 각각 ng-view 및 ng-include에서 생성되는 $ viewContentLoaded 및 $ includeContentLoaded 이벤트가 있습니다. 나는 이것이 우리가 언제 컴파일을 끝 냈는지 알 수있을만큼 가깝다고 생각합니다.

이를 바탕으로 현재 신뢰할 수있는 방식으로 수행 할 수없는 것 같습니다 . 그렇지 않으면 Angular가 즉시 이벤트를 제공했을 것입니다.

앱 부트 스트랩은 루트 범위에서 다이제스트 사이클을 실행하는 것을 의미하며 다이제스트 사이클 완료 이벤트도 없습니다.

Angular 2 디자인 문서 에 따르면 :

다이제스트가 여러 개이기 때문에 모델이 안정적인지 확인하고 구성 요소에 알리는 것은 불가능합니다. 이는 알림이 데이터를 추가로 변경하여 바인딩 프로세스를 다시 시작할 수 있기 때문입니다.

이것에 따르면 이것이 가능하지 않다는 사실이 Angular 2에서 재 작성하기로 결정한 이유 중 하나입니다.


2

라우팅을 통해 들어온 주요 부분 이후 /에 의해로드되는 조각이 있습니다.

하위 부분이로드 된 후 함수를 실행해야했고 새 지시문을 작성하고 싶지 않았고 건방진 ngIf

상위 부분의 컨트롤러 :

$scope.subIsLoaded = function() { /*do stuff*/; return true; };

부분 부분의 HTML

<element ng-if="subIsLoaded()"><!-- more html --></element>

1

서버 측 데이터 (JSP, PHP)로 JS를 생성하려면 컨트롤러가로드 될 때 자동으로로드되는 서비스에 로직을 추가 할 수 있습니다.

또한 모든 지시문의 컴파일 / 링크가 완료되었을 때 대응하려면 위의 적절한 제안 솔루션을 초기화 논리에 추가 할 수 있습니다.

module.factory('YourControllerInitService', function() {

    // add your initialization logic here

    // return empty service, because it will not be used
    return {};
});


module.controller('YourController', function (YourControllerInitService) {
});

0

이것들은 모두 훌륭한 솔루션이지만, 현재 라우팅을 사용하고 있다면이 솔루션이 가장 쉽고 최소한의 코드라는 것을 알았습니다. 'resolve'속성을 사용하여 경로를 트리거하기 전에 약속이 완료 될 때까지 기다립니다. 예 :

$routeProvider
.when("/news", {
    templateUrl: "newsView.html",
    controller: "newsController",
    resolve: {
        message: function(messageService){
            return messageService.getMessage();
    }
}

})

전체 문서를 보려면 여기를 클릭하십시오-K. Scott Allen에 대한 크레딧


0

이 예를 통해 내가 당신을 도울 수 있을까요?

사용자 정의 fancybox에서 보간 된 값으로 내용을 표시합니다.

서비스에서 "open"fancybox 메소드에서

open: function(html, $compile) {
        var el = angular.element(html);
     var compiledEl = $compile(el);
        $.fancybox.open(el); 
      }

$ compile은 컴파일 된 데이터를 반환합니다. 컴파일 된 데이터를 확인할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.