AngularJS: ng-include içinde açısal kod dosyası nasıl oluşturulur?


85

Hey köşeli bir web sayfası oluşturuyorum. Sorun şu ki, açısal olmadan inşa edilmiş bazı şeyler var ve bunları da dahil etmem gerekiyor.

Sorun bu.

Main.html dosyamda buna benzer bir şey var:

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

Kısmi.html dosyamda böyle bir şey var

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

Ve parsiyel.js'imin angularjs ile ilgisi yok. nginclude çalışıyor ve html'yi görebiliyorum, ancak javascript dosyasını hiç göremiyorum. Firebug / chrome-dev-tool'u nasıl kullanacağımı biliyorum, ancak yapılan ağ isteğini bile göremiyorum. Neyi yanlış yapıyorum?

Ben açısalların kod etiketi için özel bir anlamı olduğunu biliyorum. Geçersiz kılabilir miyim?

Yanıtlar:


101

Kabul edilen cevap 1.2.0-rc1 + ( Github sorunu ) ile çalışmayacaktır.

İşte endorama tarafından oluşturulan hızlı bir düzeltme :

/*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));

Basitçe bu dosyayı ekleyin, ngLoadScriptmodülü uygulama bağımlılığı type="text/javascript-lazy"olarak yükleyin ve kısmi olarak tembel olarak yükleyeceğiniz komut dosyası için tür olarak kullanın :

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

5
Betik etiketiniz satır içi js yerine src niteliğine sahipse bunun işe yarayacağını sanmıyorum.
Blaskovicz


1
Bu mükemmel çalışıyor, ancak istediğim bir şey daha var. Yönerge kaldırıldıktan sonra bunu nasıl kaldırırım?
SLearner

Tembel komut dosyasında denetleyici bildirdiğimde, görünümdeki denetleyiciye başvururken hata aldım. Neden biliyor musun?
Changwang Zhang

Bu hile yaptı. Kısmi olarak yüklenen bir sekme seti için sekme başlatma kodunu çalıştırmak için kullandım
LKallipo

39

Kısa cevap: AngularJS ("jqlite") bunu desteklemiyor. Sayfanıza jQuery ekleyin (Angular eklemeden önce) ve çalışmalıdır. Bkz. Https://groups.google.com/d/topic/angular/H4haaMePJU0/discussion


2
Kısmi.js bir denetleyici içeriyorsa bu nasıl çalışır? Şablon, denetleyici yüklenmeden önce oluşturulur ve bir hata verir: 'MyController' bağımsız değişkeni bir işlev değil, tanımsız oldu.
sthomps

2
@sthomps, bunun yardımcı olup olmadığına bakın: Bir denetleyiciyi dinamik olarak yükleme
Mark Rajcok

16
Bunun neden işe yaradığını anlamıyorum - tarayıcı, enjekte edilen bir komut dosyası etiketini otomatik olarak yüklemeyecek mi? Bu neden bir jQuery veya jqLite endişesi?
Scott Coates

benim için de çalıştı, <script> etiketimin içeriği angularjs ilgisizdi. JQuery'yi angularjs'den önce yüklemediğimde, aşağıdaki kısımdaki ve betik etiketi dahil her şey kaldırıldı, çok garip.
Nick Russler

20

Neemzy'nin yaklaşımını denedim ama 1.2.0-rc.3 kullanarak benim için işe yaramadı. Komut dosyası etiketi DOM'a eklenir, ancak javascript yolu yüklenmez. Yüklemeye çalıştığım javascript farklı bir etki alanından / protokolden olduğundan şüpheleniyorum. Bu yüzden farklı bir yaklaşım izledim ve Google haritalarını örnek olarak kullanarak ortaya çıkardığım şey buydu: ( Gist )

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');
                    });
                }
            }
        };
    }]);

Umarım birisi için faydalıdır.


4
Garip, 1.2.0-rc3 üzerinde kendi sürümümü harici betiklerle yaptım :) Sürümünüz zaten çok daha iyi, bunu paylaştığınız için teşekkürler!
neemzy

12

Bu yöntemi, bir komut dosyasını dinamik olarak (bir denetleyicinin içinde) yüklemek için kullandım.

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

güzel bir @azmeer
Ali

Dinamik komut dosyası yüklemesi için basit ve en iyi çözüm olduğu için oy verildi.
RLD

8

Bu artık 1.2.0-rc1'den itibaren çalışmayacak. Hızlı bir geçici çözümü açıklayan bir yorum yayınladığım bu konu hakkında daha fazla bilgi için bu konuya bakın . Burada da paylaşacağım:

// 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);
    }
}]);

Şimdiye kadarki en iyi çözüm değil, ama hey, sonraki görünümlere komut dosyası etiketleri koymuyor. Benim durumumda bunu yapmam gerekiyor Facebook / Twitter / vb. widget'lar.


4

ocLazyLoad , yönlendiriciler (örn. ui-yönlendirici) aracılığıyla şablonlara / görünümlere komut dosyalarını tembel olarak yüklemeye izin verir. İşte bir snippet

$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();
        }]
    }
});  

Ben de bunun gibi aynı sorunla karşılaştım. kurumsal uygulamada tüm rotalarınızı kullanmanız gerekir, böylece sekmelerle birlikte ng-include'i kullanmak daha iyidir, ancak ng-include'in sorunları vardır, bu da bağımlılık yükleme özelliği yoktur.
Serak Shiferaw

1

Recaptcha'yı dinamik olarak yüklemek ui-viewiçin aşağıdaki yöntemi kullanıyorum:

İçinde 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));


            }
        }
    };
});

İçinde myPartial.client.view.html:

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

bu açısal yerel komut dosyası direktifine eklenir mi yoksa onu geçersiz kılar mı? Ve bununla jquery mi kullanılıyor?
jamie

1
Ekler. Ve hayır, orada Jquery kullanılmıyor
Michael Draper

thx - 'burada jQuery kullanılmaz' -tuhaf- $(element)neden $()sözdizimine ihtiyacınız var ? ajs belgelerinden ' Angular'daki tüm eleman referansları her zaman jQuery veya jqLite ile sarılır' (bir direktifin derleme / bağlantı fonksiyonundaki eleman argümanı gibi) - bundan ve diğer deneyimlerimden - 'elementi kullanmanızı bekliyordum. ek (...) `` - sonunda kullanabileceğim şey olmamama rağmen - test ederken o parçayı gördüğümde kafam karıştı ve sadece 'element.append' ile çalışmayı denediğimde benim için çalışmadım sözdizimi
jamie

doh evet öyle, ama isterseniz bunu angular.element () ile değiştirebilirsiniz, büyük olasılıkla.
Michael Draper

0

Maalesef bu yazıdaki tüm cevaplar benim için işe yaramadı. Aşağıdaki hatayı almaya devam ettim.

"Belge" üzerine "yazma" yürütülemedi: Açıkça açılmadıkça, eşzamansız olarak yüklenen bir harici komut dosyasından bir belgeye yazmak mümkün değildir.

Bunun, ek harici JavaScript dosyalarını da çağıran ve HTML eklemeye çalışan bazı üçüncü taraf widget'ları (benim durumumda demandforce) kullandığınızda olduğunu öğrendim. Konsola ve JavaScript koduna baktığımda, bunun gibi birden çok satır fark ettim:

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

Https://github.com/krux/postscribe adresinden 3. taraf JavaScript dosyalarını (htmlParser.js ve postscribe.js) kullandım . Bu, bu gönderideki sorunu çözdü ve aynı zamanda yukarıdaki hatayı da düzeltti.

(Bu, şu anda sahip olduğum son tarihe göre hızlı ve kirli bir yoldu. Ancak 3. taraf JavaScript kitaplığını kullanmak konusunda rahat değilim. Umarım birisi daha temiz ve daha iyi bir yol bulabilir.)


0

Google reCAPTCHA'yı açıkça kullanmayı denedim. İşte örnek:

// 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));
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.