0

I found this thread How to handle multiple JS libraries with different loading times in Angular? which I am using to add d3.js to my header. I now have to add d3.legend.js aswell. How would I accomplish this in a callback-manner?

var d3js = angular.module('d3', []);

d3js.factory('d3Service', ['$document', '$q', '$rootScope', '$window',
    function($document, $q, $rootScope, $window) {
        var d = $q.defer();

        function onScriptLoad() {
            // Load client in the browser
            $rootScope.$apply(function() { d.resolve($window.d3); });
        }
        // Create a script tag with d3 as the source
        // and call our onScriptLoad callback when it
        // has been loaded

        var scriptTag = $document[0].createElement('script');
        scriptTag.type = 'text/javascript';
        scriptTag.async = true;
        scriptTag.src = 'lib/d3.v3.js';

        scriptTag.onreadystatechange = function () {
            if (this.readyState == 'complete') onScriptLoad();
        }

        scriptTag.onload = onScriptLoad;

        var s = $document[0].getElementsByTagName('body')[0];
        s.appendChild(scriptTag);

        //this is now where I have to add d3.legend.js which depends on the successful loading of d3.js.

        return {
            d3: function() { return d.promise; }
        };

    }]);

2 Answers 2

1

A cut-down version of the original idea:

var app = angular.module('SomeApp', []);
app.factory('LibraryFactory', function () {
    var factory = {};

    factory.getD3 = function(callback) {
        if(!window.d3) {
            var script = document.createElement("script");
            script.src = "https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.9/d3.min.js";
            document.head.appendChild(script);
            script.onload = function() {
                callback(window.d3);
            };
        } else {
            callback(window.d3);
        }
    };

    factory.getD3Legend = function(callback) {
        if(!window.d3.legend) {
            //...ditto
        }
    };

    return factory;
});

And to use the factory (eg, in a controller) you can chain the calls:

app.controller('SomeTrialCtrl', function ($scope, LibraryFactory) {

    LibraryFactory.getD3(function (d3) {
        LibraryFactory.getD3Legend(function (d3WithLegend) {
            // place code using the libraries here
        });
    });
});

Or in the case of d3.legend, the factory.getD3Legend function could call the getD3 function internally to keep things simpler. Like:

factory.getD3Legend = function(callback) {
    factory.getD3(function(d3) {
        if(!d3.legend) {
            //...ditto
        }
        callback(d3);
    }
};

That's the basic idea anyway. @aarosil's answer in the original post probably is more Angular-correct.

Sign up to request clarification or add additional context in comments.

Comments

0

I just loop through the array of libraries that I need to add and add them one by one see code below:

 var _libraries: [
     'scripts/d3.min.js',
     'scripts/moment.min.js'
 ]

 for (var i = 0, len = _libraries.length; i < len; i++) {
     var s = document.createElement('script');
     s.type = 'text/javascript';
     s.src = _libraries[i];

     document.body.appendChild(s);
 }

Hope this helps.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.