AngularJS : ng-include 내부에서 각도로드 스크립트를 만드는 방법은 무엇입니까?


85

안녕하세요 저는 각도로 웹 페이지를 만들고 있습니다. 문제는 이미 앵귤러없이 구축 된 무언가가 있고 그것들도 포함시켜야한다는 것입니다.

문제는 이것입니다.

내 main.html에 다음과 같은 것이 있습니다.

<ngInclude src="partial.html">
</ngInclude>

그리고 내 partial.html은 다음과 같습니다.

<h2> heading 1 <h2>
<script type="text/javascript" src="static/js/partial.js">
</script>

그리고 내 partial.js는 angularjs와 관련이 없습니다. nginclude가 작동하고 html을 볼 수 있지만 javascript 파일이 전혀로드되지는 않습니다. firebug / chrome-dev-tool을 사용하는 방법을 알고 있지만 네트워크 요청이 생성되는 것을 볼 수 없습니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

나는 각도가 스크립트 태그에 특별한 의미를 가지고 있습니다. 재정의 할 수 있습니까?

답변:


101

허용되는 답변은 1.2.0-rc1 + ( Github 문제 ) 에서 작동하지 않습니다 .

endorama가 만든 빠른 수정은 다음과 같습니다 .

/*global angular */
(function (ng) {
  'use strict';

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

  app.directive('script', function() {
    return {
      restrict: 'E',
      scope: false,
      link: function(scope, elem, attr) {
        if (attr.type === 'text/javascript-lazy') {
          var code = elem.text();
          var f = new Function(code);
          f();
        }
      }
    };
  });

}(angular));

이 파일을 추가하고 ngLoadScript모듈을 애플리케이션 종속성 type="text/javascript-lazy"으로로드하고 부분적으로 느리게로드 할 스크립트 유형으로 사용하십시오 .

<script type="text/javascript-lazy">
  console.log("It works!");
</script>

5
스크립트 태그에 인라인 js가 아닌 src 속성이 있으면 이것이 작동한다고 생각하지 않습니다.
Blaskovicz 2014


1
이것은 완벽하게 작동하지만 내가 원하는 것이 하나 더 있습니다. 디렉티브가 폐기 된 후 어떻게 제거합니까?
SLearner

lazy 스크립트에서 컨트롤러를 선언 할 때 뷰에서 컨트롤러를 참조 할 때 오류가 발생했습니다. 그 이유를 아십니까?
Changwang Zhang

그게 속임수였습니다. 부분에로드 된 탭 세트에 대한 탭 초기화 코드를 실행하는 데 사용했습니다
LKallipo

39

짧은 대답 : AngularJS ( "jqlite")는 이것을 지원하지 않습니다. 페이지에 jQuery를 포함하면 (Angular를 포함하기 전에) 작동합니다. 참조 https://groups.google.com/d/topic/angular/H4haaMePJU0/discussion를


2
partial.js에 컨트롤러가 포함 된 경우 어떻게 작동합니까? 컨트롤러가로드되기 전에 템플릿이 렌더링되고 오류가 발생합니다. 인수 'MyController'는 함수가 아니므로 정의되지 않았습니다.
sthomps

2
@sthomps, 이것이 도움이되는지 확인하십시오 : 컨트롤러를 동적으로로드
Mark Rajcok

16
이것이 작동하는 이유를 이해할 수 없습니다. 브라우저가 삽입 된 스크립트 태그를 자동으로로드하지 않습니까? 이것이 왜 jQuery 또는 jqLite 문제입니까?
Scott Coates 2013 년

저에게도 효과가 있었지만 <script> 태그의 내용은 angularjs와 관련이 없었습니다. angularjs 전에 jQuery를로드하지 않았을 때 아래 부분의 모든 부분과 스크립트 태그가 제거되었습니다. 매우 이상했습니다.
Nick Russler 2015 년

20

나는 neemzy의 접근 방식을 시도했지만 1.2.0-rc.3을 사용하여 작동하지 않았습니다. 스크립트 태그는 DOM에 삽입되지만 자바 스크립트 경로는로드되지 않습니다. 로드하려는 자바 스크립트가 다른 도메인 / 프로토콜에서 왔기 때문이라고 생각합니다. 그래서 저는 다른 접근 방식을 취했고, 이것이 구글지도를 예로 들어 제가 생각해 낸 것입니다. ( 요점 )

angular.module('testApp', []).
    directive('lazyLoad', ['$window', '$q', function ($window, $q) {
        function load_script() {
            var s = document.createElement('script'); // use global document since Angular's $document is weak
            s.src = 'https://maps.googleapis.com/maps/api/js?sensor=false&callback=initialize';
            document.body.appendChild(s);
        }
        function lazyLoadApi(key) {
            var deferred = $q.defer();
            $window.initialize = function () {
                deferred.resolve();
            };
            // thanks to Emil Stenström: http://friendlybit.com/js/lazy-loading-asyncronous-javascript/
            if ($window.attachEvent) {  
                $window.attachEvent('onload', load_script); 
            } else {
                $window.addEventListener('load', load_script, false);
            }
            return deferred.promise;
        }
        return {
            restrict: 'E',
            link: function (scope, element, attrs) { // function content is optional
            // in this example, it shows how and when the promises are resolved
                if ($window.google && $window.google.maps) {
                    console.log('gmaps already loaded');
                } else {
                    lazyLoadApi().then(function () {
                        console.log('promise resolved');
                        if ($window.google && $window.google.maps) {
                            console.log('gmaps loaded');
                        } else {
                            console.log('gmaps not loaded');
                        }
                    }, function () {
                        console.log('promise rejected');
                    });
                }
            }
        };
    }]);

누군가에게 도움이되기를 바랍니다.


4
이상하게도, 1.2.0-rc3에서 외부 스크립트로 나만의 버전을 만들었습니다. :) 어쨌든 귀하의 버전이 훨씬 좋습니다. 공유해 주셔서 감사합니다!
neemzy

12

이 방법을 사용하여 스크립트 파일을 동적으로로드했습니다 (컨트롤러 내부).

var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "https://maps.googleapis.com/maps/api/js";
document.body.appendChild(script);

좋은 하나의 @azmeer
알리

동적 스크립트 로딩을위한 간단하고 최상의 솔루션이기 때문에 투표했습니다.
RLD

8

1.2.0-rc1에서는 더 이상 작동하지 않습니다. 이에 대한 자세한 내용은 이 문제 를 참조하십시오 . 여기에 빠른 해결 방법을 설명하는 댓글이 게시되었습니다. 여기에서도 공유하겠습니다.

// Quick fix : replace the script tag you want to load by a <div load-script></div>.
// Then write a loadScript directive that creates your script tag and appends it to your div.
// Took me one minute.

// This means that in your view, instead of :
<script src="/path/to/my/file.js"></script>

// You'll have :
<div ng-load-script></div>

// And then write a directive like :
angular.module('myModule', []).directive('loadScript', [function() {
    return function(scope, element, attrs) {
        angular.element('<script src="/path/to/my/file.js"></script>').appendTo(element);
    }
}]);

최고의 솔루션은 아니지만 후속 뷰에 스크립트 태그를 넣는 것도 아닙니다. 제 경우에는 Facebook / Twitter 등을 사용하기 위해 이렇게해야합니다. 위젯.


4

ocLazyLoad 는 라우터 (예 : ui-router)를 통해 템플릿 /보기에서 스크립트를 느리게로드 할 수 있습니다. 여기 스니 플릿이 있습니다

$stateProvider.state('parent', {
    url: "/",
    resolve: {
        loadMyService: ['$ocLazyLoad', function($ocLazyLoad) {
             return $ocLazyLoad.load('js/ServiceTest.js');
        }]
    }
})
.state('parent.child', {
    resolve: {
        test: ['loadMyService', '$ServiceTest', function(loadMyService, $ServiceTest) {
            // you can use your service
            $ServiceTest.doSomething();
        }]
    }
});  

나는 이와 같은 문제에 직면했습니다. 기업 응용 프로그램에서 당신은 더 사용할 수 있도록 모든 경로를 사용할 필요가 탭으로 겨-포함하지만 겨-포함하는 것은 .. 그 종속 로딩 기능이없는 느릅 나무 자사의 문제가
Serak Shiferaw

1

에서 recaptcha를 동적으로로드하려면 ui-view다음 방법을 사용합니다.

에서 application.js:

    .directive('script', function($parse, $rootScope, $compile) {
    return {
        restrict: 'E',
        terminal: true,
        link: function(scope, element, attr) {
            if (attr.ngSrc) {
                 var domElem = '<script src="'+attr.ngSrc+'" async defer></script>';
                 $(element).append($compile(domElem)(scope));


            }
        }
    };
});

에서 myPartial.client.view.html:

 <script type="application/javascript" ng-src="http://www.google.com/recaptcha/api.js?render=explicit&onload=vcRecaptchaApiLoaded"></script>

각도 네이티브 스크립트 지시문에 추가하거나 무시합니까? 그리고 그것과 함께 jquery를 사용하고 있습니까?
jamie

1
추가됩니다. 그리고 더, 더 JQuery와이 사용되지 않습니다
마이클 드레이퍼

thx- '여기에 jQuery가 사용되지 않음'-이상한- $(element)$()구문 이 필요합니까? ajs 문서에서 'Angular의 모든 요소 참조는 항상 jQuery 또는 jqLite로 래핑됩니다'(예 : 지시문의 컴파일 / 링크 함수의 요소 인수) -그래서 저와 다른 경험에서- '요소를 사용할 것으로 기대했습니다. append (...)`-결국 내가 사용할 수있는 것이 아니었지만-테스트 할 때 그 부분을 보았을 때 혼란 스러웠고 'element.append'로만 작업하려고 시도했을 때 나를 위해 작동하지 않았습니다. 구문
제이미

그렇습니다.하지만 원하는 경우 angular.element ()로 바꿀 수 있습니다.
Michael Draper

0

불행히도이 게시물의 모든 답변이 저에게 효과적이지 않았습니다. 다음과 같은 오류가 계속 발생했습니다.

'문서'에서 '쓰기'를 실행하지 못했습니다. 명시 적으로 열리지 않는 한 비동기 적으로로드 된 외부 스크립트에서 문서에 쓸 수 없습니다.

추가 외부 JavaScript 파일을 호출하고 HTML을 삽입하려고하는 타사 위젯 (제 경우에는 수요자)을 사용하는 경우 이런 일이 발생한다는 것을 알았습니다. 콘솔과 JavaScript 코드를 살펴보면 다음과 같은 여러 줄을 발견했습니다.

document.write("<script type='text/javascript' "..."'></script>");

https://github.com/krux/postscribe 에서 타사 JavaScript 파일 (htmlParser.js 및 postscribe.js)을 사용했습니다. . 이 게시물의 문제를 해결하고 위의 오류를 동시에 수정했습니다.

(이것은 지금의 촉박 한 기한 아래서 빠르고 더러운 방법이었습니다. 그러나 타사 JavaScript 라이브러리를 사용하는 것이 편하지 않습니다. 누군가가 더 깨끗하고 더 나은 방법을 찾을 수 있기를 바랍니다.)


0

Google reCAPTCHA를 명시 적으로 사용해 보았습니다. 다음은 그 예입니다.

// put somewhere in your index.html
<script type="text/javascript">
var onloadCallback = function() {
  grecaptcha.render('your-recaptcha-element', {
    'sitekey' : '6Ldcfv8SAAAAAB1DwJTM6T7qcJhVqhqtss_HzS3z'
  });
};

//link function of Angularjs directive
link: function (scope, element, attrs) {
  ...
  var domElem = '<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script>';
  $('#your-recaptcha-element').append($compile(domElem)(scope));
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.