AngularJS + JQuery : angularjs에서 동적 콘텐츠를 작동시키는 방법


84

jQuery와 AngularJS를 모두 사용하는 Ajax 앱에서 작업 중입니다.

jQuery의 html함수를 사용하여 div의 콘텐츠 (AngularJS 바인딩 포함)를 업데이트 할 때 AngularJS 바인딩이 작동하지 않습니다.

다음은 내가하려는 코드입니다.

$(document).ready(function() {
  $("#refreshButton").click(function() {
    $("#dynamicContent").html("<button ng-click='count = count + 1' ng-init='count=0'>Increment</button><span>count: {{count}} </span>")
  });
});
</style><script src="http://docs.angularjs.org/angular-1.0.1.min.js"></script><style>.ng-invalid {
  border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="">
  <div id='dynamicContent'>
    <button ng-click="count = count + 1" ng-init="count=0">
        Increment
      </button>
    <span>count: {{count}} </span>
  </div>


  <button id='refreshButton'>
    Refresh
  </button>
</div>

ID가있는 div 내부에 동적 콘텐츠 #dynamicContent가 있고 새로 고침을 클릭하면이 div의 콘텐츠를 업데이트하는 새로 고침 버튼이 있습니다. 콘텐츠를 새로 고치지 않으면 Increment가 예상대로 작동하지만 새로 고치면 AngularJS 바인딩이 작동을 멈 춥니 다.

이것은 AngularJS에서 유효하지 않을 수 있지만 처음에는 jQuery로 애플리케이션을 빌드하고 나중에 AngularJS를 사용하기 시작했기 때문에 모든 것을 AngularJS로 마이그레이션 할 수 없습니다. AngularJS에서이 작업을 수행하는 데 도움을 주시면 대단히 감사하겠습니다.


1
이 기능에 JQuery를 사용하는 특별한 이유가 있습니까? <이이기 때문에 친절하고 쉽게 각도에 의해 덮여 jsfiddle.net/pkozlowski_opensource/YCrFD/2 >
pkozlowski.opensource

3
이것은 문제를 보여주는 실제 사용 사례의 단순화 된 버전입니다. 실제 애플리케이션에서 동적 콘텐츠는 html로 jquery에 전달되는 grails taglib에 의해 생성됩니다. 그래서 나는 grails taglib의 모든 로직을 angularjs로 포팅하여 순수한 angularjs로 만들 수 없습니다.
Raja

1
@ pkozlowski.opensource, 그 링크가 죽었습니까? 또한 outdoors.stackexchange.com에 가입해야합니다. :)
Liam

답변:


115

$compileangular가 바인딩을 수행 할 수 있도록 DOM에 삽입하기 전에 HTML 문자열 을 호출해야합니다 .

바이올린에서는 다음과 같이 보일 것입니다.

$("#dynamicContent").html(
  $compile(
    "<button ng-click='count = count + 1' ng-init='count=0'>Increment</button><span>count: {{count}} </span>"
  )(scope)
);

물론, $compile이 작업을 수행하려면 컨트롤러에 주입해야합니다.

$compile문서 에서 더 많은 것을 읽으십시오 .


2
감사합니다 Noah, 컨트롤러 메서드에서 수행하고 해당 컨트롤러 메서드를 버튼의 클릭 이벤트에 직접 바인딩하면 컴파일이 작동합니다. 다음은 작업 입니다. 하지만 실제 앱에서는 다른 jquery 함수에서 컨트롤러 메서드를 호출해야했습니다. 그래서 범위 개체에 대한 참조를 잡고 작동하지 않는 다시 컴파일하기 위해 refresh 메서드를 호출했습니다. 여기에 예가 있습니다. 이 예제가 작동하도록 도와 줄 수 있습니까?
Raja

1
@Raja 각도 프레임 워크 외부에서 각도 메서드 / 표현식을 호출 할 때 $ scope. $ apply () 를 호출 하여 예외 처리, 감시 실행 등의 적절한 범위 수명주기를 수행해야합니다. jsfiddle.net/fABdD/14
Artem Andreev

1
@ArtemAndreev 정확히 맞습니다. @Raja 아키텍처에 적합한 경우 함수 자체 $scope.$apply()로 호출을 이동할 수도 있습니다 refresh(). jsfiddle.net/nfreitas/8xkeh/1
Noah Freitas

3
angular-1.0.1.min.js원래 예제 의 링크 는 404입니다. 다음은 @ ArtemAndreev-s 예제의 업데이트 된 작업 버전입니다. jsfiddle.net/pmorch/fABdD/186 및 @NoahFreitas 예제 : jsfiddle.net/pmorch/8xkeh/43
Peter V. Mørch

1
$ compile을 사용하고 컨트롤러 내에서 DOM을 조작하면 테스트 할 수없는 코드를 갖게됩니다. 컨트롤러가 아닌 DOM을 변경하기 위해 지시문을 사용해야합니다.
Enzey

57

동적 콘텐츠를 제어 할 수없는 경우를위한 또 다른 솔루션

이것은 지시문을 통해 요소를로드하지 않은 경우 작동합니다 (예 : 주석 처리 된 jsfiddles의 예제에서와 같이).

콘텐츠 정리

JQuery를 사용하는 경우 선택할 수 있도록 콘텐츠를 div로 래핑합니다 . 요소를 얻기 위해 네이티브 자바 스크립트를 사용하도록 선택할 수도 있습니다.

<div class="selector">
    <grid-filter columnname="LastNameFirstName" gridname="HomeGrid"></grid-filter>
</div>

Angular Injector 사용

$ compile에 대한 참조가없는 경우 다음 코드를 사용하여 얻을 수 있습니다.

$(".selector").each(function () {
    var content = $(this);
    angular.element(document).injector().invoke(function($compile) {
        var scope = angular.element(content).scope();
        $compile(content)(scope);
    });
});

요약

원래 게시물은 $ compile 참조가 편리하다고 가정 한 것 같습니다. 참고 문헌이 있으면 분명히 쉽지만 나는 그렇지 않았습니다.

이전 코드의 한 가지주의 사항

minify 시나리오와 함께 asp.net/mvc 번들을 사용하는 경우 릴리스 모드에서 배포 할 때 문제가 발생합니다. 문제는 잡힌 오류 : [$ injector : unpr]의 형태로 나타납니다.이 문제는 각 자바 스크립트 코드를 엉망으로 만드는 미니 파이어로 인해 발생합니다.

이를 해결하는 방법은 다음과 같습니다 .

이전 코드 조각을 다음 오버로드로 바꿉니다.

...
angular.element(document).injector().invoke(
[
    "$compile", function($compile) {
        var scope = angular.element(content).scope();
        $compile(content)(scope);
    }
]);
...

이것은 내가 그것을 모으기 전에 많은 슬픔을 일으켰습니다.


1
위의 코드가 범위와 컴파일에 대한 설명을 사용할 수 있도록 해주었으므로 감사합니다. 때때로 당신은 쉬운 부분을 놓친다 :)
Abs

컴파일 후 $ digest를해야했습니다.
Knu

2
절대 생명, I는 각 응용 프로그램에 연결 할 때 모든 각도 선 (善)을 사용할 수 있습니다 내 코드에서 각도에 대한 조건부 검사 추가
LiamRyan

18

@jwize의 답변에 추가

angular.element(document).injector()오류가 발생 했기 때문에 injector is not defined AJAX 호출 후 또는 jQuery를 사용하여 DOM을 변경할 때 실행할 수있는 함수를 만들었습니다.

  function compileAngularElement( elSelector) {

        var elSelector = (typeof elSelector == 'string') ? elSelector : null ;  
            // The new element to be added
        if (elSelector != null ) {
            var $div = $( elSelector );

                // The parent of the new element
                var $target = $("[ng-app]");

              angular.element($target).injector().invoke(['$compile', function ($compile) {
                        var $scope = angular.element($target).scope();
                        $compile($div)($scope);
                        // Finally, refresh the watch expressions in the new element
                        $scope.$apply();
                    }]);
            }

        }

새 요소의 선택자를 전달하여 사용하십시오. 이렇게

compileAngularElement( '.user' ) ; 

감사합니다. $ scope 함수 내에서 HTML을 즉석에서 생성하여 대화 상자에 UIKit을 사용하는 패키지로 제 생명을 구했습니다. 참고로, 필자의 경우 $ [ "data-ng-controller]")에 맞게 $ target의 선택기를 변경하고 $ scope.apply (); 이 기능이 각도 콜백 이미 호출 된 이후 (그래서 이미 복용으로 적용)
zontar

@zontar target는 인수에서 가져 와서 동적으로 만들 수도 있습니다 .
shyammakwana.me
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.