[javascript] AngularJS : AngularJS가 템플릿을 렌더링 한 후 추가 코드를 실행하는 방법은 무엇입니까?

DOM에 Angular 템플릿이 있습니다. 컨트롤러가 서비스에서 새 데이터를 가져 오면 $ scope에서 모델을 업데이트하고 템플릿을 다시 렌더링합니다. 지금까지는 모두 좋았습니다.

문제는 템플릿을 다시 렌더링하고 DOM (이 경우 jQuery 플러그인)에 넣은 후에 추가 작업을 수행해야한다는 것입니다.

AfterRender와 같은 청취 이벤트가 있어야하는 것처럼 보이지만 그러한 것을 찾을 수 없습니다. 지시어가 갈 수있는 방법 일지 모르지만 너무 일찍 발사되는 것처럼 보였습니다.

여기 내 문제를 간략히 설명하는 jsFiddle이 있습니다. Fiddle-AngularIssue

== 업데이트 ==

유용한 의견을 바탕으로 DOM 조작을 처리하기 위해 지시문으로 전환했으며 지시문 안에 $ watch 모델을 구현했습니다. 그러나 여전히 동일한 기본 문제가 있습니다. 템플릿이 컴파일되어 DOM에 삽입되기 전에 $ watch 이벤트 내부의 코드가 실행되므로 jquery 플러그인은 항상 빈 테이블을 평가합니다.

흥미롭게도 비동기 호출을 제거하면 모든 것이 잘 작동하므로 올바른 방향으로 나아가는 단계입니다.

다음은 이러한 변경 사항을 반영하기 위해 업데이트 된 Fiddle입니다. http://jsfiddle.net/uNREn/12/



답변

이 게시물은 오래되었지만 코드를 다음과 같이 변경합니다.

scope.$watch("assignments", function (value) {//I change here
  var val = value || null;
  if (val)
    element.dataTable({"bDestroy": true});
  });
}

jsfiddle을 참조하십시오 .

도움이 되길 바랍니다


답변

먼저, 렌더링을 망칠 적절한 장소는 지시어입니다. 내 조언은 jQuery 플러그인을 조작하는 DOM을 이와 같은 지시문으로 감싸는 것입니다.

나는 같은 문제가 있었고이 발췌 문장을 생각해 냈습니다. 그것은 사용 $watch$evalAsync지시가 좋아 후 코드 실행을 보장하기 위해 ng-repeat해결과 같은 템플릿 된 {{ value }}렌더링되었다.

app.directive('name', function() {
    return {
        link: function($scope, element, attrs) {
            // Trigger when number of children changes,
            // including by directives like ng-repeat
            var watch = $scope.$watch(function() {
                return element.children().length;
            }, function() {
                // Wait for templates to render
                $scope.$evalAsync(function() {
                    // Finally, directives are evaluated
                    // and templates are renderer here
                    var children = element.children();
                    console.log(children);
                });
            });
        },
    };
});

이것이 약간의 투쟁을 예방하는 데 도움이되기를 바랍니다.


답변

비동기 작업을 원한다면 Misko의 조언에 따라 $ timeout () 대신 작동하지 않습니다.

$timeout(function () { $scope.assignmentsLoaded(data); }, 1000);

$ evalAsync () 사용하십시오 (작동합니다)

$scope.$evalAsync(function() { $scope.assignmentsLoaded(data); } );

바이올린 . 또한 $ scope.assignments를 수정하여 데이터 / 모델 변경을 시뮬레이션하는 “데이터 행 제거”링크를 추가하여 데이터 변경이 작동 함을 보여줍니다.

개념적 개요 페이지 의 런타임 섹션에서는 현재 스택 프레임 외부에서 발생해야하지만 브라우저가 렌더링되기 전에 evalAsync를 사용해야한다고 설명합니다. (여기서 … “현재 스택 프레임”에는 아마도 Angular DOM 업데이트가 포함되어있을 것입니다.) 브라우저가 렌더링 된 후에 무언가가 필요하면 $ timeout을 사용하십시오.

그러나 이미 알았 듯이 여기서 비동기 작업이 필요하지 않다고 생각합니다.


답변

가장 간단한 (저렴하고 쾌활한) 솔루션은 마지막으로 렌더링 된 요소의 끝에 ng-show = “someFunctionThatAlwaysReturnsZeroOrNothing ()”으로 빈 범위를 추가하는 것입니다. 이 기능은 span 요소가 표시되어야하는지 확인할 때 실행됩니다. 이 함수에서 다른 코드를 실행하십시오.

나는 이것이 가장 우아한 방법이 아니라는 것을 알고 있지만 그것은 나를 위해 작동합니다 …

애니메이션이 시작될 때 로딩 표시기를 제거 해야하는 부분이 약간 바뀌었지만 비슷한 상황이 발생했습니다. 모바일 장치에서 각도가 애니메이션보다 표시가 훨씬 빠르게 초기화되었으며 로딩 표시기가 ng-cloak을 사용하는 것만으로는 충분하지 않았습니다 실제 데이터가 표시되기 전에 제거되었습니다. 이 경우 방금 리턴 0 함수를 첫 번째 렌더링 된 요소에 추가했으며이 함수에서로드 표시기를 숨기는 var를 뒤집 었습니다. (물론이 기능으로 트리거되는 로딩 표시기에 ng-hide를 추가했습니다.


답변

나는 당신이 $ evalAsync http://docs.angularjs.org/api/ng.$rootScope.Scope#$evalAsync를 찾고 있다고 생각합니다.


답변

마지막으로 해결책을 찾았습니다. 내 컬렉션을 업데이트하기 위해 REST 서비스를 사용하고있었습니다. 데이터 테이블을 변환하기 위해 jquery는 다음 코드입니다.

$scope.$watchCollection( 'conferences', function( old, nuew ) {
        if( old === nuew ) return;
        $( '#dataTablex' ).dataTable().fnDestroy();
        $timeout(function () {
                $( '#dataTablex' ).dataTable();
        });
    });


답변

나는 이것을 아주 자주해야했습니다. 지시어가 있으며 모델 항목이 DOM에 완전히로드 된 후 일부 jquery 작업을 수행해야합니다. 그래서 나는 내 논리를 링크에 넣었다 : 지시자의 함수와 코드를 setTimeout (function () {…..}, 1); setTimout은 DOM이로드 된 후 시작되며 1 밀리 초는 코드가 실행되기 전에 DOM이로드 된 후 가장 짧은 시간입니다. 이것은 나를 위해 작동하는 것 같지만 템플릿이로드되면 angular가 이벤트를 발생시켜 해당 템플릿에서 사용하는 지시문이 jquery 작업을 수행하고 DOM 요소에 액세스 할 수 있기를 바랍니다. 도움이 되었기를 바랍니다.