简体   繁体   中英

How to conditionally include assets in the <head> with Angular

I am building a one-page Angular app. One of the views has content which depends on an external javascript library.

I don't want to include this external JS resource on every view of the site, just the single view which depends on it.

What is the best way to conditionally include blocks of code based on the current view?

If it's possible I'm hoping I can place in the something like this:

<script ng-if="view == 'view1'" type='text/javascript' src='http://webplayer.unity3d.com/download_webplayer-3.x/3.0/uo/UnityObject2.js'></script>

So you should include the library script in page.

Then within directive bound to elements it needs to act on do the initialization.

app.directive('unity', function () {
    return {
        link: function (scope, element, attrs) {
            // element is jQuery object when jQuery.js is included in page 
            // before angular - or it is a jQLite object similar to a jQuery object

            // config code

            u.initPlugin(element[0], "web_ovar_beta.unity3d");
        }
    }
});

Usage in view:

<div unity></div>

This can easily be expanded to pass in attributes to the directive from controller

It is

<script ng-if="view == 'view1'" type='text/javascript' ng-src='http://webplayer.unity3d.com/download_webplayer-3.x/3.0/uo/UnityObject2.js'></script>

And it is something that you don't want to do. It doesn't guarantee that the script won't be loaded twice. Since the script is being used for particular view, make it one-time resolving service

app.factory('unityResolver', function ($document, $rootScope, $q, $timeout) {
  var deferred = $q.defer();
  var script = angular.element('<script>')[0]; 

  script.src = '...';
  script.async = true;
  script.onload = script.onreadystatechange = function () {
    if (['loaded', 'complete', undefined].indexOf(script.readyState) < 0)
      return;

    script.onload = script.onreadystatechange = null;

    deferred.resolve();
    $rootScope.$apply();
  }

  script.onerror = function onerror() {
    script.onerror = null;

    deferred.reject();
    $rootScope.$apply();
  };

  $timeout(onerror, 20000);
  $document.find('head').append(script);

  return deferred.promise;
});

and use it in view/route resolve .

What your wanting to in turn is impossible.

You can get Javascript to include a javascript file if you want however if your using AJAX to load the content that is needed leave it in there it would be the same amount of time to load anyway. but once a file has been loaded into JavaScript it finished with you can remove the file from your HTML but the JavaScript engine still has the content of that file loaded in to it.

Try it in your browsers(chrome or FF with Firebug) inspector now: open a new tab and go to about:blank then put the code below into the console

var include = (function(){
   // the reference to the script
   var theScript;

   return function (filename, status){
     if(status == 'on'){
       // adding a script tag
       var head = document.getElementsByTagName('head')[0];

       theScript= document.createElement('script');
       theScript.src = filename;
       theScript.type = "text/javascript";

       head.appendChild( theScript )
     }else{
       // removing it again
       theScript.parentNode.removeChild( theScript );
     }
   }
})();

taken from Remove specific <script> tag in <head> tag by onclick event

then in your inspector's console

include("https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js", 'on')

now check Elements and you will see jQuery loaded in the pages head tag. and type jQuery into console and you will see function (a,b){return new n.fn.init(a,b)}

And then use this into your console

include("https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js", 'off')

and check your elements tab again the script tag will have gone. however go back to console and type jQuery again and you will see function (a,b){return new n.fn.init(a,b)} as even though you have unloaded the file you can't remove the executed code from memory.

You have 2 options another framework page gets loaded into an iFrame or if you want to use Anagular to load the View in then just include the file in your head there is no point not having and then removing it as once it is loaded it's loaded

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM