IT Share you

AngularJS가 HTML 렌더링을 완료 한 후 jQuery 코드 실행

shareyou 2020. 11. 8. 11:35
반응형

AngularJS가 HTML 렌더링을 완료 한 후 jQuery 코드 실행


컨트롤러에서 $ http 또는 $ resource 서비스를 사용하여 JSON 데이터를 얻습니다. 그런 다음이 데이터를 $ scope에 쓰고 AngularJS가 페이지의 HTML 구조를 업데이트합니다. 내 문제는 Angular ng-repeat지시문으로 채워진 목록 (즉, HTML DOM 요소)의 새로운 크기 (너비 및 높이)가 무엇인지 알아야한다는 것입니다 . 결과적으로 Angular가 DOM 구조 업데이트를 마친 직후에 자바 스크립트 코드를 실행해야합니다. 이를 수행하는 올바른 방법은 무엇입니까? 지난 4 시간 동안 인터넷을 검색했지만 내 문제에 대한 해결책을 찾지 못했습니다.

이것은 JSON 데이터를받는 방법입니다.

var tradesInfo = TradesInfo.get({}, function(data){
    console.log(data);
    $scope.source.profile = data.profile;
            $scope.trades = $scope.source.profile.trades;
        $scope.activetrade = $scope.trades[0];
        $scope.ready = true;


    init();  //I need to call this function after update is complete

});

그리고 이것은 init()기능 에서 일어나는 일입니다 .

function init(){
    alert($('#wrapper').width());
    alert($('#wrapper').height());
}

이 문제를 쉽게 해결할 수있는 방법이 있다는 것을 알고 있지만 지금은 찾을 수 없습니다. 미리 감사드립니다.


실제로이 경우 각도 방법은 쉬운 방법이 아니라 유일한 올바른 방법입니다. :)

지시문을 작성하고 높이를 알고 싶은 요소에 연결해야합니다. 컨트롤러에서 이벤트를 브로드 캐스트하면 지시문이 이벤트를 잡아서 DOM 조작을 수행 할 수 있습니다. 컨트롤러에서 절대로.

var tradesInfo = TradesInfo.get({}, function(data){
    console.log(data);
    $scope.source.profile = data.profile;
    ...

    $scope.$broadcast('dataloaded');
});


directive('heightStuff', ['$timeout', function ($timeout) {
    return {
        link: function ($scope, element, attrs) {
            $scope.$on('dataloaded', function () {
                $timeout(function () { // You might need this timeout to be sure its run after DOM render.
                    element.width()
                    element.height()
                }, 0, false);
            })
        }
    };
}]);

Olivér의 대답은 좋지만 문제가 있습니다. 이벤트를 브로드 캐스트하는 것을 잊으면 자바 스크립트가 실행되지 않지만 데이터가 변경되었을 수 있습니다. 또 다른 해결책은 범위의 변경 사항을 관찰하는 것입니다. 예를 들면 다음과 같습니다.

var tradesInfo = TradesInfo.get({}, function(data) {
  console.log(data);
  $scope.profile = data.profile;
  // ...
});


directive('heightStuff', ['$timeout',
  function($timeout) {
    return {
      scope: {
        myData: '='
      },
      link: function($scope, element, attrs) {
        $scope.$watch('myData', function() {
          $timeout(function() { // You might need this timeout to be sure its run after DOM render.
            element.width()
            element.height()
          }, 0, false);
        })
      }
    };
  }
]);
<div height-stuff my-data="profile"></div>

이렇게 하면 맞춤 이벤트 없이도 데이터가 변경 될 때마다 자바 스크립트 함수가 호출 됩니다 .


JQuery로 작업하기위한 또 다른 제안. 지시문에서 생성 된 그리드에 대해이 작업을 수행해야했습니다. 그리드의 특정 행으로 스크롤하고 싶었습니다. $ emit을 사용하여 지시문에서 부모 컨트롤러로 브로드 캐스트합니다.

컨트롤러에서 :

    ['$timeout',function($timeout){
...
 $scope.$on('dataloaded', function () {
            $timeout(function () { // You might need this timeout to be sure its run after DOM render.
                $scope.scrollToPosition();
            }, 0, false);
        });
        $scope.scrollToPosition = function () {
            var rowpos = $('#row_' + $scope.selectedActionID, "#runGrid").position();
            var tablepost = $('table', "#runGrid").position();
            $('#runGrid').scrollTop(rowpos.top - tablepost.top);
        }

지시에서

.directive('runGrid',['$timeout', function ($timeout) {
        // This directive generates the grip of data
        return {
            restrict: 'E',  //DOM Element
            scope: {    //define isolated scope
                list: '=',   //use the parent object
                selected: "="
            },

            templateUrl: '/CampaignFlow/StaticContent/Runs/run.grid.0.0.0.0.htm',  //HTML template URL

            controller: ['$scope', function ($scope) {  //the directive private controller, whith its private scope
                //$scope.statusList = [{ data_1: 11, data_2: 12 }, { data_1: 21, data_2: 22 }, { data_1: 31, data_2: 32 }];
                //Controller contains sort functionallity

                $scope.sort = { column: null, direction: 1 }
                $scope.column = null;
                $scope.direction = "asc";
                $scope.sortColumn = function (id) {
                    if(id!=$scope.column) {
                        $scope.column = id;
                        $scope.direction = "asc";
                    } else {
                        $scope.column = null;
                    }
                }
                $scope.toggleDir = function () {
                    $scope.direction = ($scope.direction == "asc") ? "desc" : "asc";
                }
               $scope.$emit('dataloaded');
            }]


        };
    }])

다음은 그리드 지시문 html 템플릿의 일부입니다.

 <div style="overflow-y:auto;height: 200px;" id="runGrid">
            <table class="table table-striped" style="table-layout:fixed">
           <tbody>
                <tr  ng-repeat="status in list" id="row_{{status.action_id}}" ng-class="(status.action_id==selected)?'selected':''">
                    <td>

목록 및 선택된 매개 변수는 지시문을 사용하는 html에서 주입됩니다.

<run-grid list="list" selected="selectedActionID"></run-grid>

앞의 답변은 ngRepeat가 완료된 후 실행하는 데 필요한 코드가 각도 코드라는 것을 받아들이 기 때문에 다른 답변을 추가하고 싶습니다.이 경우 위의 모든 답변은 위의 모든 답변이 다른 것보다 더 일반적인 솔루션을 제공합니다. 다이제스트 수명주기 단계가 중요한 경우 Ben Nadel의 블로그에서 $ eval 대신 $ parse를 사용하는 것을 제외하고 살펴볼 수 있습니다.

But in my experience, as the OP states, it is usually running some jQuery plugins or methods on the finally compiled DOM, which in that case I found that the most simple solution is to create a directive with a setTimeout, since the setTimeout function gets pushed to the end of the queue of the browser, its always right after everything is done in angular, usually ng-repeat which continues after it's parents postLinking function

angular.module('myApp', [])
.directive('pluginNameOrWhatever', function() {
  return function(scope, element, attrs) {        
    setTimeout(function doWork(){
      //jquery code and plugins
    }, 0);        
  };
});

For whoever wondering why not to use $timeout, its that it causes another digest cycle that is completely unnecessary.

EDIT:

Thanx to drzaus for the link to how to use $timeout without causing digest http://www.codelord.net/2015/10/14/angular-nitpicking-differences-between-timeout-and-settimeout/

참고URL : https://stackoverflow.com/questions/16935766/run-jquery-code-after-angularjs-completes-rendering-html

반응형