4

I am using Grails 2.4.1 and the Grails Asset Pipeline Plugin version 1.9.7.

I have a javascript file (it defines an AngularJS directive) which needs to reference a static HTML file (which will be used as the template for the AngularJS Directive).

How do i reference the HTML file within the asset directory?

Project Structure:

  • grails-app
  • assets
    • javascripts
      • directives
        • hierarchyviewer.js
        • hierarchyviewer.html

Project Structure when using the Angular Template Asset pipeline grails plugin

  • grails-app
    • assets
      • javascripts
        • directives
          • hierarchyviewer.js
      • templates
        • hierarchyviewer.tpl.html

directivea.js contains:

angular.module('HierarchyViewer', []).directive('hierarchyviewer',function(){
    return {
        restrict: 'EA',
        scope: {},
        replace: true,
        controller: function ($scope, $http) {
        },
        templateUrl: 'hierarchyviewer.tpl.html'
    }

})

However; when I try to load a page that references the directive, I get a 404 for the directives/directivea.html reference.

How do I reference the template properly when using the Asset Pipeline plugin?

Randyaa
  • 2,935
  • 4
  • 36
  • 49

2 Answers2

3

Angular Template Asset Pipeline Plugin author here. A couple tweaks and this should work for you.

  • The plugin expects the module names to be in camel case.
  • The plugin also removes the .tpl from the file name so you'll end up with a file named hierarchyviewertemplate.js in this case
  • Make sure the file names (excluding the extension) are unique.

On that last point, since The Asset Pipeline plugin will ignore the parent folders within the assets directory, a file in each of the following locations would cause a conflict:

  • /assets/javascripts/hierarchyviewertemplate.js
  • /assets/templates/hierarchyviewertemplate.tpl.html

In terms of the actual code, something like this should work better for you:

//= require_self
//= require_tree /hierarchyViewer

angular.module('hierarchyViewer', []).directive('hierarchyviewer',function(){
    return {
        restrict: 'EA',
        scope: {},
        replace: true,
        controller: function ($scope, $http) {
        },
        templateUrl: 'hierarchyviewertemplate.html'
    }
});

This would assume that your hierarchyviewertemplate.tpl.html file is located at

grails-app -> assets -> templates -> heirarchyViewer -> hierarchyviewertemplate.tpl.html

If your template is contained within a plugin, replace require_tree with require_full_tree

Hope that helps.

craigburke
  • 46
  • 7
  • I can give this a shot tomorrow but I feel like this is the exact setup I've had several times. Is there a good way to know the plugin is actually picking up the template and pushing it into the $templateCache ? – Randyaa Aug 20 '14 at 00:43
  • The one difference is HierarchyViewer vs hierarchyViewer for the module name... Not sure I've tried that. I've tried various camelcase variations for the template name reference (in my templateUrl reference in the directive) and file name itself. – Randyaa Aug 20 '14 at 00:44
  • if it's linked up right, you should see something like this in your HTML in development mode: – craigburke Aug 20 '14 at 00:47
  • hierarchyViewer vs HierarchyViewer will make a difference. I don't think I explicitly mention that in the docs, but will add it to make it more obvious. – craigburke Aug 20 '14 at 00:49
  • Yeah I'll try that first thing tomorrow and let you know. If it doesn't work I'll try to get a snapshot of what's in $templateCache to see what is being pushed in. – Randyaa Aug 20 '14 at 00:56
  • I've changed the Module name to be hierarchyViewer and I'm still getting the same result. I've stepped through the javascript debugger and when my templateUrl is referenced there is NOTHING in the $templateCache, so the lookup fails and it tries to use the url I've provided. What would cause the plugin not to add the template to the cache? – Randyaa Aug 20 '14 at 13:05
  • What do your require directives at the top of your directivea.js file look like? Do you have something like this: //= require_self //= require_tree heirarchy-viewer – craigburke Aug 20 '14 at 13:11
  • I threw a debug statement in the TemplateProcessorUtil.getModuleName method... and i don't get anything which suggest to me that the plugin isn't really running. What would cause that? – Randyaa Aug 20 '14 at 13:11
  • I added the directives to the top of my answer. Do you have something like that in your JS file? – craigburke Aug 20 '14 at 13:13
  • I had the require_self but not the tree... i just added the require_tree and no change. – Randyaa Aug 20 '14 at 13:17
  • Where is your hierarchyviewer.tpl.html file located right now? – craigburke Aug 20 '14 at 13:19
  • grails-app/assets/templates/hierarchyViewer/hierarchyviewer.tpl.html – Randyaa Aug 20 '14 at 13:20
  • I just noticed you had /templates/hierarchy-viewer/hierarchyviewer.tpl.html as the expected path. i just moved it there with no difference. – Randyaa Aug 20 '14 at 13:22
  • Ok, sorry, I assumed the folder you were using was named heirarchy-viewer. That means require_tree needs to be adjusted. Changing my answer now. – craigburke Aug 20 '14 at 13:23
  • I've tried both variations require_tree hierarchy-viewer & require_tree hierarchyViewer. still no luck. With each variation i'm checking the contents of $templateCache and I still never see anything. regardless of what paths i'm referencing and what filenames i use... if the plugin were working properly wouldn't the $templateCache always contain some mapping? – Randyaa Aug 20 '14 at 13:32
  • I think we're getting tripped up on the actual path to your template. I changed my answer to use the absolute path in the directive. This should have occurred to me earlier since I actually added that functionality to the asset pipeline :) – craigburke Aug 20 '14 at 13:36
  • definitely getting closer with that... I now hit the breakpoint i set in the HtmlTemplateProcessor and I can see the content of my template. However; when $templateCache.get("hierarchyviewer.html"); is called in the javascript, $templateCache still has no mappings. – Randyaa Aug 20 '14 at 13:43
  • whoa i just noticed a whole slew of exceptions in the console now: groovy.lang.MissingPropertyException: No such property: assetConfig for class: DUMMY at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:50) at org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:49) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:231) at DUMMY$_closure1.doCall(DUMMY.groovy:1) – Randyaa Aug 20 '14 at 13:45
  • I think the exceptions were from my debugging... i'm not getting them any more. I'm still hitting the HtmlTemplateProcessor break point and i can see the content of my template, but the $templateCache is still empty :( – Randyaa Aug 20 '14 at 13:50
  • something interesting of note... i now see /assets/hierarchyViewer/hierarchyviewer.js?compile=false AND /assets/hierarchyviewer/hierarchyviewer.js?compile=false in the browser, both have the same content though – Randyaa Aug 20 '14 at 13:51
  • ok I figured it out... The issue is my template has the same name as my javascript file. Also, your camel-case thing about the module name is completely wrong, the plugin assumes it's all lowercase. – Randyaa Aug 20 '14 at 13:57
  • I guess in your case it would, but heirarchy-viewer.tpl.html or heirarchy_viewer.tpl.html would translate to the module heirarchyViewer. I'm glad it's figured it out though, and you've given me some things that needed clarified in the documentation so thanks for that. – craigburke Aug 20 '14 at 14:01
  • so interesting turn... This works fantastically when the asset is in the same project as the reference, but when all of this is part of a plugin and I reference that plugin with another Grails app, it seems the plugin doesn't pick up the template and push it into the $templateCache even though it's contained within the asset directory of the referenced plugin. – Randyaa Aug 20 '14 at 19:09
1

there is a plugin called angular-template-asset-pipeline. The essence of it is that it will put your .tpl.htm templates in the $templateCache. Then you could use it like this (example from the docs):

angular.module('myApp.appSection', ['ngRoute'])
.config(function($routeProvider) {
      $routeProvider
          .when('/index', {
              templateUrl: 'index.htm'
          })
          .otherwise({redirectTo: '/index'});
});
Mario David
  • 1,595
  • 11
  • 19
  • I've tried using that plugin and i get: Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost:8980/app-name-here/directivea.html Error: [$compile:tpload] http://errors.angularjs.org/1.2.21/$compile/tpload?p0=directivea.html – Randyaa Aug 19 '14 at 19:18
  • I've updated the question to include the structure & template reference i used when using the pipeline plugin you mention. – Randyaa Aug 19 '14 at 19:23
  • in the docs, the example is that the path for the template is `/grails-app/assets/templates/my-app/app-section/index.tpl.htm`. You mentioned in your question, that your template is called `directivea.html`. Does changing the name to `directivea.tpl.html` has any effect? – Mario David Aug 19 '14 at 19:27
  • sorry... the filename is directivea.tpl.html but according to the docs for the plugin you reference it with just directivea.html. i'm updating the question now to reflect that difference... – Randyaa Aug 19 '14 at 19:28
  • as you can see from the example in the docs, after the templates directory the directory structure reflects the module name and then the template name. In your example you have the module name `MyModule` and the template name `directivea` but your directory structure is `grails-app/assets/templates/directivea.tpl.html`. It should be `grails-app/assets/templates/my-module/directivea.tpl.html`. The other thing is, that you do this: `templateUrl: 'directives/directivea.html'` which seems not to be correct. According to the docs it should be `templateUrl: 'directivea.html'` – Mario David Aug 19 '14 at 19:37
  • i will inject the modulename into the directory structure and see... howver; see the comment (NOTE) in the code example for the name... when using the angular template plugin i change that path to just the name of the file – Randyaa Aug 19 '14 at 19:38
  • Looking at the code of the angular-template-asset-pipeline my suspicion is it has something to do with the specific filenames/paths i'm using so i've corrected the question with the actual names. – Randyaa Aug 19 '14 at 19:54
  • Refer [this sample app](http://angular-grails.interwebs.io/) and [blog from author of the plugin](http://www.craigburke.com/2014/07/24/angular-grails-asset-pipeline.html). If you are still stuck then I can come up with a sample app as I did earlier for resources plugin. @Randyaa – dmahapatro Aug 19 '14 at 19:58
  • Given how the plugin is intended to work i would expect to hit a breakpoint (from angular.js) on launching the page in this function: run: function(block) { runBlocks.push(block); return this; }. I actually hit the break point... but block and runBlocks are both undefined. I also found this in the plugin documentation: 'Note the use of require_self above to make sure that the myApp.appSection module is defined before the template files are imported.' which would seem to point to me needing to add require_self to my hierarchyviewer.js so I did... and still nothing. – Randyaa Aug 19 '14 at 20:18
  • Walking through the code of the plugin I think the module name it will use is templates.hierarchyviewer.hiersrchyviewer.tpl.html which is obviously not right... – Randyaa Aug 19 '14 at 20:43
  • So i used a javascript debugger and monitored the 'put' method on the $templateCache. the plugin is supposed to PUT the content of my template into the $templateCache. nothing seems to happen :( – Randyaa Aug 19 '14 at 21:13