How do you point to an AngularJS Template from within a JS file provided by a Grails plugin? - angularjs

I have a Grails app which pulls in several Grails Plugins. These plugins need to be reused by several other Grails apps not just my own.
In a Resources Bundle in one of the Grails Plugins I have the following defined:
leaving this for completeness, but I have since switched to the Asset-Pipline
modules = {
directivea {
resource url: 'directives/directivea/directivea.js'
resource url: 'services/restapis.js'
}
}
In a Javascript file in one of the plugins I have the following directive defined:
ModuleA.directive('directivea',function() {
return {
restrict: 'EA',
scope: {
'objId' : '='
},
replace: true,
link: function(){
$scope.ObjId = attributes[''];
$scope.someFunction($scope.ObjId);
},
controller: function(){
$scope.someFunction = function(objId){
//some stuff happens here
};
},
templateUrl: 'directives/directivea/directivea.html'
}
});
It seems to be executing the controller just fine but when it tries to pull in the template it chokes on:
GET /appname/directives/directivea/directivea.html
404 (Not Found)
This makes sense because that's not where the partial template will be. Where would it be though? How can I keep that information isolated to within the plugin but usable by all the downstream applications? I'd like to avoid defining in-line templates if I can.
**EDIT TO INCLUDE STRUCTURE**
Structure of Plugin:
grails-app
conf
PluginNameForGrailsResources.groovy
BuildConfig.groovy
controllers
PluginControllerA.groovy
PluginControllerB.groovy
domain
PluginDomainA.groovy
web-app
css
directives
directivea
directivea.js
directivea.html
services
restapis.js
application.properties
PluginNameForGrailsGrailsPlugin.groovy
Structure of the application referencing my Plugin:
grails-app
conf
BuildConfig.groovy
controllers
domain
views
layouts
main.gsp
index.gsp (references to directivea via resources r:require tag)
web-app
css
main.css
js
index.js
application.properties
**EDIT TO INCLUDE STRUCTURE POST-ASSET-PLUGIN-SWITCHOVER**
no more Resources defined, BuildConfig.groovy now references the asset pipline instead of Resources, no more files in web-app
grails-app
conf
BuildConfig.groovy
controllers
PluginControllerA.groovy
PluginControllerB.groovy
domain
PluginDomainA.groovy
assets
javascripts
directivea
directivea.js
directivea.html
services
restapis.js
application.properties
PluginNameForGrailsGrailsPlugin.groovy

Using the Grails Resource plugin
Refer this sample grails app which uses this grails plugin.
Plugin hosts an angular module. I tried to keep it simple by just adding a directive and no other module. Also note that I have used static/.. in the templateUrl in directive.
Also refer Config.groovy in the app which uses below config
grails.resources.adhoc.includes = ['/images/**', '/css/**', '/js/**', '/img/**']
as mentioned in the answer to this question. May be you are hitting this issue.
Give it a try. "Hello World" is rendered from the directive present in an angular module inside the plugin.
If you are using latest version of Grails then I would suggest to switch to asset pipeline whenever convenient.
Using the Grails Asset Plugin
Use the Grails asset-pipeline plugin (v 1.9.7 as of this posting) and the Grails Angular-template-asset-pipeline plugin (v 1.2.5 as of this posting).
For details on exactly how to set this up, see the answers to How to reference a static HTML resource using the Grails Asset Pipeline plugin.
Primarily, ensure your Angular JS module is lowercase or uses _'s or -'s in the name and that your template file has a slightly different filename (ignoring the extension) than any of the javascript assets you're including.

Note that the javascript is referencing things from the web-app root, not from the resources or assets directory. You can find more about Angular routing from the core documentation: $route
So templateUrl: directives/directivea/directivea.html needs to actually reference a file in the /web-app/directives/directivea/directivea.html directory.
Note that the resources plugin does not seem to be very modular, and global files need to be specified for sharing (and most other things). If you move to grails 2.4 and the assets plugin, you can do modular file paths.

Related

Where to put ng1 templates in an angular hybrid application built by angular-cli?

I'm trying to build an angular hybrid application out of a angular.js application. I'm following the official documentation (https://angular.io/guide/upgrade). I reached and completed this step: https://angular.io/guide/upgrade#bootstrapping-hybrid-applications.
I'm using angular ui-router 0.3.1 to handle the routing of my application. Therefore, using the config function on my main module, and the $stateProvider service, I've mapped each route to an angular.js controller and a template specified by the templateUrl parameter.
My application seems to startup correctly but the templates cannot be loaded because they cannot be found (404 error). This is normal because they are not imported in the dist folder where my application is built when I use the ng build angular-cli command line.
How can I configure my application so that my angular.js html templates get copied in the dist folder when my angluar application is built by angular-cli?
Thanks in advance!
So actually it appears my question was a duplicate of that one: Angular CLI with Hybrid app ng-build.
The idea is to use the assets array from angular-cli.json. Glob enables to select recursively all html files from the folder of your choice and to put them in a subfolder of dist:
"asssets": [{"glob": "**/*.html", "input": "../src-ng1", "output": "./src-ng1"}]

Is it possible to define AngularJS route's templateUrl path fully agnostic to IIS app folder structure?

I have have done some research here and in general, but couldnt find a proper way to implement this.
We have and MVC/WebAPI2/AngularJS Web app.
I am trying to achive this goal: being able to put my app anywhere in IIS app folder structure without any code changes. That means, get rid of any IIS Application name in my code.
Here is a simple fragment of ng-route path defined:
.when("/", { templateUrl: "Home/Main", controller: "MainController",
controllerAs: "vm" })
Now, the IIS app is called ReportsWeb (but could be any name)
If I set ReportsWeb app under Default Web Site root:
http://localhost/ReportsWeb/
then everything works fine, and templateUrl page is loaded fine.
But if the app is placed under another IIS App (the one we have here is called RealSuiteApps, which is itself under Default Web Site)
http://localhost/RealSuiteApps/ReportsWeb/
then, the templates are not loaded, since constructed URL for templateUrl is no longer valid:
http://localhost/RealSuiteApps/Home/Main
If I change templateUrl to "/Home/Main", constructed URL is not valid again
http://localhost/Home/Main
If I change templateUrl to "./Home/Main", constructed URL is not valid again
http://localhost/RealSuiteApps/Home/Main
Is it possible to define templateUrl only relative to the latest App name in the IIS hierarchy without hardcoding all these names, so that it will work in any IIS app tree
http://localhost/App1/App2/App3/ReportsWeb/
Thanks!
I use grunt-html2js tool to convert all html templates to Javascript at build time, which uses Angular's template cache.
I've defined my grunt task to overwrite the default module naming to templates/ so that I can reference any template easily:
html2js: {
options: {
rename: function (moduleName) {
return moduleName.replace(/^.*[\/\\]/, 'templates/');
}
},
all: {
src: ['./src/**/*.html', '!./src/index.html'],
dest: 'tmp/templates.js'
}
},
This will create a templates.js file that I can include as a script tag. Then I can access any template like so:
templatUrl: 'templates/my-template-filename.html'
Regardless of where it's path was in the source code.

AngularJS templates don't work with Spring

I have developed a REST application using Spring in NetBeans IDE.
Here is the relevant dir structure:
I want to integrate Angular functionality into it, but will prefer to keep it as a single app, rather than separate Angular and Spring apps.
The main index.html file should show the template home.html on the front page.
The Problem:
Adding HTML files to the templates folder doesn't seem to work in the Angular application. If I try to access the index.html and home.html files through Angular, I get a 404 error, but I can open them directly.
Here's the controller in my Spring application for these two files:
#RequestMapping("/")
public String index() {
return "index";
}
#RequestMapping("/home")
public String home() {
return "home";
}
I have written AngularJS code before by itself, and I didn't have any problems.
Am I mixing some things that I shouldn't?
Do I create all my AngularJS code in a separate folder, away from src/main/resources?
Spring maps your files placed in src/main/resources/static to the root directory of your application. This means a CSS file in your src/main/resources/static/css/ folder can be accessed by simply using the /css relative path.
Static resources such as CSS, Javascript, templates or images should therefore be placed in the static folder, where Angular will be able to access it.
This restriction does not extend to your main index.html file, and you can place it in the main project directory or under templates.
Answer taken from JBNizet in comments.

Yeoman Directive Template Not Found

I have an angular website that I'm developing with Yeoman. My site works great when I'm iterating during development. When I go to deploy the minified, uglified, versionified site after development and I got the following error while loading a directive template in the console when the site loaded.
Error: [$compile:tpload] Failed to load template: views/template_name.html (HTTP status: 404 Not Found)
I'm using Windows 7 with the all of the yeoman web client tool set (grunt, npm, bower, compass, etc.).
The reason for this error was that windows files are NOT case sensitive, and obviously javascript strings ARE. My solution was to make sure the case of my templateUrl field in my directives matched exactly with the case of the file in my views folder.
Explanation:
Yeoman does this great thing where it will create an angularjs template cache for you during it's minification/uglification/versionification/deployment process in the minified javascript file. It finds your templates referenced from your templateUrls and bundles them up into plain text in a javascript file, so that you don't have to do anything and it just works! The problem I ran into is that the template cache is indexed with the name of the file in the templateUrl field in my directive.
In development mode, node loads up the template from the file on the server (on my windows machine) and this load is case insensitive. In the so-called "dist" mode with this template cache, this templateUrl lookup is now case sensitive.
My solution was to make sure the case of my templateUrl field matched exactly with the case of the file in my views folder.

environment specific config with angularjs

I am working on creating a website with Angularjs and WebAPI as backend support with Visual studio.
I have defined the url to webapi in app.config.js as an app constant:
var serviceBase = 'http://localhost/Webapiservice/';
app.constant('ngAppSettings', {
apiServiceBaseUri: serviceBase,
clientId: 'ngTestApp'
});
Now for QA environments (http://QAServer/Webapiservice/), the webapi resides at a different URL, the same goes for our production environment (http://ProdServer/Webapiservice/).
I can manually update the js file to the appropriate location. But is there a way to automate this process so webAPI is pointing to the correct URL?
Is it possible to do this with grunt? Again I have never used grunt before.
ngConstant does a great job, along with grunt: https://github.com/werk85/grunt-ng-constant. This way you can specify your environments as JSON files and on compile/run time, grunt generates a enviornment.js file with a module (I call mine always ENV), which can be injected in every part of your application.
I would do something like this:
angular
.module('app', [])
.value('$path', {
rest : "http://localhost/Webapiservice"
})
you will call something like this:
app.constant('ngAppSettings', {
apiServiceBaseUri: $path.rest,
clientId: 'ngTestApp'
});

Resources