Loading ng-include partials from local pre-loaded

2020-06-23 08:43发布

问题:

I have my template pre-loaded in a javascript string array, like var t = JST['firstTemplate'], where t would be like,

<div>This scope has a value of {{value}}</div>

How can I use this pre-loaded template in an ng-include directive?

Note that my template in this scenario can be more complex, with possible nested view and templates and their own nested scopes and controllers. So I am not sure if any of the ng-bind directives would help?

UPDATE:

Looking at the source of ng-include it appears that a good way to do this would be to decouple the template loading logic into a customizable provider.

The current default loading mechanism simply does a $http.get with $templateCache as the cache provider. It seems like I can inject my template content in JST['firstTemplate'] into the template cache, but I'd have to do that at startup time, for every template.

$templateCache.put('firstTemplate', JST['firstTemplate']);

and then have,

<div ng-include="firstTemplate"></div>

I could also write a custom directive that goes side-by side with every ng-include, that somehow does this pre-caching of templates. That again seem clunky.

UPDATE #2

I'm going to try overriding the templateCache, so that it uses my already pre-loaded JST hash. Will post the results if this works.

回答1:

Here is the solution I found to work, and it's not a hack like I was thinking earlier (above :-) Basically, decorate the $templateCache.get method using standard $provide.decorator so that cache gets look in my local pre-loaded cache. It just works.

angular.module('app').config([
  '$provide', 
  function($provide) {
    $provide.decorator('$templateCache', function($delegate, $sniffer) {
      var originalGet = $delegate.get;

      $delegate.get = function(key) {
        var value;
        value = originalGet(key);
        if (!value) {
          // JST is where my partials and other templates are stored
          // If not already found in the cache, look there...
          value = JST[key]();
          if (value) {
            $delegate.put(key, value);
          }
        }
        return value;
      };

      return $delegate;
    });

    return this;
  }
]);

If you're wondering why I have this stuff in JST, we use a rails backend and the rails asset pipeline to deliver all angular assets. The JST templates allow us to bundle all templates and load them into the app during initialization, and avoid additional server roundtrips that are normally required when fetching partials and other template content.

The above patch makes all of this works with angular.



回答2:

Instead of ng-include, use ng-bind-html:

<div ng-bind-html="t"></div>

On your controller, place the template on the $scope:

$scope.t = JST['firstTemplate'];

You will need to include ngSanitize as a submodule (don't forget to add angular-sanitize.js too):

angular.module('app', ['ngSanitize']);


回答3:

today i am faced with the same problem, here is my solution:

A custom directive, which return the JST"server/info" as template:

/* jstTemplate.js */

/**
 * @desc template loader for JST templates
 * @example <div jst-template="server/info.html"></div>
 */


angular
    .module('myApp')
    .directive('jstTemplate', jstTemplate);

function jstTemplate() {
    return {
        restrict: 'A',
        template: function(element, attrs) {
            return JST[attrs.jstTemplate]();
        }
    }
};

Usage:

<div class="box">
    <div jst-template="server/info.html"></div>
</div>

The attrs.jstTemplate contains the value, we provided in the directive.

Cheers, Niklas