0

In AngularJS I'm trying to manually load a template that uses a predefined controller.

I call a WebApi to get a list of available templates. When this list is received I should load each template onto the page. Each template also uses an AngularJS controller so the connection between the template and the preloaded controller must work.

After some googling I ended up on this previous (and somewhat old) question: AngularJS Manually Render Controller and Template

It seems to do exactly what I want, but it has a directive that uses more parameters than I need. Also, I don't have directives for my templates. I just can't wrap my head around how to get it to do what I want.

How can I get ExampleTemplateToLoad.html to be loaded by code, inserted into div#LoadedTemplates while functioning like a normal template using a controller?

main.js

var myApp = angular.module('myApp', [.....]);
myApp.config(function($routeProvider) {
    $routeProvider.when('/', { templateUrl : '/mainTemplate.html' });
});

myApp.controller('mainController', function ($scope, $http) {
    $http.get('/api/getListOfTemplateScripts').success(function (data) {
        // This returns a list of scripts that should be loaded
        // Scripts are loaded using https://github.com/ded/script.js
        // These scripts show up in "Sources" in Chrome Developer Tools,
        // and any syntax errors in these scripts are also displayed in
        // the console, so the script is definitely loaded
        angular.forEach(data, function (scriptFile, key) {
            $script(scriptFile, function() {
                console.log(scriptFile + " loaded");
            });
        });
    })
    .then(function() {
        $http.get('/api/getListOfTemplate').success(function (data) {
            // This returns a list that includes ExampleTemplateToLoad.html
            // The template should then be loaded into div#LoadedTemplates
            angular.forEach(data, function (templateFile, key) {
                // This is logged *after* "scriptToLoad loaded" in the console
                console.log('Loading template ' + templateFile);
            });
        });
    });
});

mainTemplate.html

<div ng-controller="mainController">
    <div id="LoadedTemplates"></div>
</div>

ExampleTemplateToLoad.html

<div ng-controller="loadedTemplateController">
    <!-- Do whatever the template needs to do, using variables defined
         in $scope as it would normally do -->
</div>

ExampleTemplateControllerToLoad.js

myApp.controller('loadedTemplateController', function ($scope, $http) {
});
Community
  • 1
  • 1
TheHvidsten
  • 4,028
  • 3
  • 29
  • 62

1 Answers1

1

Not sure if ur supposed to be modifying DOM from a controller but I'd try binding your "LoadedTemplates" to a variable (using ng-model) and in the controller, once you get the dynamic template back from the $http.get, get a reference to the div, i.e.

var target = $document[0].getElementById('LoadedTemplates')

and then do something along the lines of:

element.append(htmlReturnedByService);
$compile( element.contents() )( $scope );

Haven't tested, but maybe this helps :D

  • First error in console is `scope is not defined`. If I try to replace `scope` with `$scope` I get `Argument 'loadedTemplateController' is not a function, got undefined`. This is due to the lazy loading of the template's script file. If I put the controller in `main.js` it works. I'm updating the code above to also show lazy loading of scripts. – TheHvidsten May 25 '16 at 12:59
  • Though your browser might be loading the script, the controller has to be registered in your angular app. Try using $controllerProvider.register instead of $script? – Wagner Danda da Silva Filho May 25 '16 at 13:19
  • How do I use `$controllerProvider.register` when all I have is a link to a JS file? – TheHvidsten May 25 '16 at 13:24
  • Never mind to the last comment. If I, in myApp.config save a reference to $controllerProvider.register, I can use that reference in my lazy loaded JS file instead of myApp.controller, and now it works. Now to get this to work in a directive, as you are correct in saying the DOM shouldn't be modified from a controller. – TheHvidsten May 25 '16 at 13:30
  • @GTHvidsten well, glad I'm helping a bit :) – Wagner Danda da Silva Filho May 25 '16 at 13:39
  • Your bit definitely pointed me in the right direction, and now I have a directive working that does exactly what I wanted to to. I'll see if I can get a working JSFiddle going and link it later. Thanks :) – TheHvidsten May 25 '16 at 13:51
  • Here's a working plunker example: http://plnkr.co/edit/3kMPuSHmDuahhSFA0Nuq?p=preview – TheHvidsten May 25 '16 at 14:28