How to setup Grails and AngularJS partial templates
Asked Answered
K

4

5

I am realizing a project using AngularJS for the front end, and Grails for the backend.

  • Angular JS => Single page application
  • Grails => REST API to be used in the WebApp itself and 3rd party apps.

This is how I setup the project:

web-app
   |
   |_____ js ( angular controllers, modules, partial templates.)
   |
   |_____ images
   |
   |_____ css


grails-app
   |
   |_____ views ( in here I have my main view, the one I use at the first user request )

Rather than using the Resources Plugin, I prefer building my own front end with Grunt, and then I only link the final files inside the layout itself.

I structured the js folder in web-app to contain a partials folder with all the partial templates to be called within AngularJS

This is my pretty standard angular code to load the views:

angular.module('myapp', []).
  config(['$routeProvider', function($routeProvider) {
  $routeProvider
    .when('/invoices', {
        templateUrl: 'partials/invoices-list.html',   
        controller: InvoiceListCtrl
    })
    .when('/invoices/:invoiceId', {
        templateUrl: 'partials/invoice-details.html', 
        controller: InvoiceDetailCtrl}
    )
    .otherwise({redirectTo: '/dashboard'}, {
        templateUrl: 'partials/dashboard.html', 
        controller: DashboardCtrl
    });
}]);

What happens is that Angular is unable to get those partial templates, since the partial folder is not copied in the tomcat work directory.

I don't know which other approach can be used for a Grails powered project.

Kendakendal answered 19/9, 2013 at 8:1 Comment(3)
Please improve your question - e.g. what have you tried; show some code...Uncourtly
I have a very similar issue except my Partials are contained within the web-app directory of a Grails Plugin instead of the Grails app. Any one have any thoughts on how to reference them?Redoubt
Have you found a solution?Townspeople
B
0

I believe the issue is that the static resource is not descended from the default grails-app directory so you need to include the full path from the document root, e.g. templateUrl: '/partials/invoices-list.html',

Here is my set up for ui-router:

App.config([
  '$stateProvider'
  '$urlRouterProvider'

  ($stateProvider, $urlRouterProvider) ->

    $urlRouterProvider.otherwise("/")

    $stateProvider
      .state('intro', {
        url: "/",
        templateUrl: '/templates/intro.html'
      })
Backpack answered 19/9, 2013 at 13:25 Comment(2)
Sorry I don't see how your implementation is different from mine. Can you please explain how do you structure your partial templates folders?Kendakendal
My structure is the same as yours.Backpack
A
0

I serve my partials/views via standard ajax requests.

class ViewController {

  def invoiceList() {
    render(template: 'invoiceList')
  }
  ...
}

$routeProvider
    .when('/invoices', {
        templateUrl: contextPath + '/view/invoiceList',   
        controller: InvoiceListCtrl
    })

contextPath is derived from ${request.contextPath} that I store in a global variable in my main gsp.

Applied answered 19/9, 2013 at 11:39 Comment(1)
so you basically keep the usual structure of a standard grails project? How do you do to run your e2e tests? About the contextPath variable you use, if I can I would suggest to config your grails path to run under the main localhost, so you can avoid to pollute your JS global name space ;)Kendakendal
B
0

I believe the issue is that the static resource is not descended from the default grails-app directory so you need to include the full path from the document root, e.g. templateUrl: '/partials/invoices-list.html',

Here is my set up for ui-router:

App.config([
  '$stateProvider'
  '$urlRouterProvider'

  ($stateProvider, $urlRouterProvider) ->

    $urlRouterProvider.otherwise("/")

    $stateProvider
      .state('intro', {
        url: "/",
        templateUrl: '/templates/intro.html'
      })
Backpack answered 19/9, 2013 at 13:25 Comment(2)
Sorry I don't see how your implementation is different from mine. Can you please explain how do you structure your partial templates folders?Kendakendal
My structure is the same as yours.Backpack
A
0

By default, all the files in the web-app folder are copied to a folder called static in the war. (You can change this behaviour. See the Grails Documentation).

In your example, you can check the partial files in following urls.

http://localhost:8080/yourApp/static/js/partials/invoices-list.html
http://localhost:8080/yourApp/static/js/partials/invoices-details.html
http://localhost:8080/yourApp/static/js/partials/dashboard.html

So, what you need to do is to figure out the path to this files. Something like this:

angular.module('myapp', []).
  config(['$routeProvider', function($routeProvider) {
  $routeProvider
    .when('/invoices', {
        templateUrl: '../static/js/partials/invoices-list.html',   
        controller: InvoiceListCtrl
    })
    .when('/invoices/:invoiceId', {
        templateUrl: '../static/js/partials/invoice-details.html', 
        controller: InvoiceDetailCtrl}
    )
    .otherwise({redirectTo: '/dashboard'}, {
        templateUrl: '../static/js/partials/dashboard.html', 
        controller: DashboardCtrl
    });
}]);

Its important to notice that the templateUrl path should not be related to JS file.

Another example:

grails-app
    views
        mydomain
            index.gsp
web-app
    js
        partials
            mydomain-detail.html
            mydomain-list.html
        controllers
            mydomain-controllers.js

The resources:

http://localhost:8080/myApp/mydomain/  
http://localhost:8080/myApp/static/js/partials/mydomain-detail.html  
http://localhost:8080/myApp/static/js/partials/mydomain-list.html  

The route configuration:

angular.module('myapp', []).
  config(['$routeProvider', function($routeProvider) {
  $routeProvider
    .when('/list', {
        templateUrl: '../static/js/partials/mydomain-detail.html',   
        controller: MyDomainListCtrl
    })
    .when('/show/:id', {
        templateUrl: '../static/js/partials/mydomain-detail.html', 
        controller: MyDomainDetailCtrl}
    )
    .otherwise({
         redirectTo: '/list'
    });
}]);
Applique answered 9/5, 2014 at 5:17 Comment(0)
S
0

as an alternative to James' answer you may use GSP directly. See my answer in another thread.

Regarding contextPath: I would say that you automatically get the right context if you don't add the preceding slash.

templateUrl: 'view/invoiceList'

Best regards, Björn

P.S. Sorry for adding this as a full answer, I would have preferred it as a comment to James'. However, the system denied me to add a comment :-(

Seamount answered 11/11, 2014 at 9:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.