18

I'm trying to integrate AngularJS within a Rails app. I have a Rails app with a books controller and book model. In the Rails index view I have this, and AngularJS should take over from here:

.page_text{"ng-app" => "books"}
  .row
    .twelve.columns
      %div{"ng-view" => ""}

And the AngularJS controller looks like this:

function BooksOverviewCtrl($scope, $http) {
  $http.get('/books.json').success(function(data) {
    $scope.books = data;
  });
}
BooksOverviewCtrl.$inject = ['$scope', '$http'];

And this is the routeProvider:

angular.module('books', []).
  config(['$routeProvider', function($routeProvider) {
  $routeProvider.
      when('/books', { templateUrl: 'books/book-overview.html.haml',   controller: BooksOverviewCtrl });
}]);

Currently, the AngularJS view is in "app/assets/javascripts/angularjs/books/book-overview.html.haml". When I load the page, it says page not found, so where do I have to store the AngularJS views in my Rails app? This is the error:

GET http://localhost:3000/books/book-overview.html.haml 404 (Not Found)

9 Answers 9

21

I use the $templateCache to handle this. So in the view I have:

<script type="text/ng-template" id="bookOverview.html">
  <%= render partial: "book-overview" %>
</script>

Then with $routeProvider you can just:

$routeProvider
  .when('/books', {
    templateUrl: 'bookOverview.html',
    controller: BooksOverviewCtrl 
  });

This way you can just keep your views in the app/views/books directory where you would normally keep them.

Sign up to request clarification or add additional context in comments.

1 Comment

Just one addition i took me time to figure out. The <script type="text/ng-template"> is placed in parent view of the page so it is rendered at page load.
9

After some researching, I found there are two ways to deal with this. The first option is the way both Mahbub and Adnan Doric mention: store the files in the public folder because they are staic html files anyway.

Although this works it feels not natural for me, because then the files get scattered. Some are in the public folder, and others are in the assets/javascripts folder. Not my preferred option, but it might work well for other people.

The second option is to store the routes in a specific file, like "assets/javascripts/routes.js.erb". Because of the ".erb" it is possible to use the Rails asset_path within the file and create a relative path like this:

when('/books', { templateUrl: "<%= asset_path('book-overview.html.haml') %>",   controller: BooksOverviewCtrl });

Maybe not the perfect solution, but for me this works best, because now all my Angular files are kept together within the "assets/javascripts" folder.

3 Comments

Although this method will get you up and running, it causes a server round-trip. Solutions are discussed here groups.google.com/forum/#!topic/angular/V3hMGIDwE3o
But then where do you store book-overview.html.haml? I tested this method with a view from app/views, and got a 404.
if it's true that this causes a server round trip.. then it pretty much defeats the purpose of having a single page web app which is one of the main pluses of frameworks like angular
3

If you use the angular-rails-templates gem you can get them into the rails asset pipeline and use the template cache from angular.

Links:

Comments

2

You put AngularJS partials in public folder WITHOUT disabling the asset pipeline, just make sure it is accessible in your browser at the specified URL.

Comments

1

I created a new folder in the App/Assets/Javascript called Angular. The Angular folder contains sub-folder for controllers, views, services and directives.

Now to reference a view, lets say sample.html. This is what my templateUrl path looked like.

.when('/sample', { templateUrl: '/assets/angular/views/sample.html', controller: 'SampleCtrl' })

This way All the Angular code resides in one single folder and is not scattered all over the place. Also, the Rails Asset Pipeline can be leveraged for minification and compression of Angular's Controllers and Services.

Comments

1

I also suggest using Angular Rails Templates

Gemfile

gem 'angular-rails-templates'

$ bundle install

application.js

//= require angular-rails-templates

app.js

angular.module('myApp', ['templates'])

Now, when you include templateUrl: 'books/book-overview.html.haml' it will search through your assets folder for the correct view.

Comments

0

I've turned the asset pipeline off in config/application.rb and put all the files in public folder. Since the client side files (angularJS project) don't need any processing, filters, i chose that way.

Comments

0

The following might be good if you want to keep the two separated completely.

One option might be to create a file system symbolic link between the /ngapp/dist or /ngapp/build folder and the /public folder or a subfolder within /public. Use a grunt/node server to develop and test in, so you don't have to rebuild each time, and then grunt build to the linked /ngapp/dist folder when you are ready to push to your remote server.

This keeps the AngularJS folder separate from the Rails app, but allows access only to the final build files, not the source files within your AngularJS app folder.

Comments

0

You can try to use gem js_assets

Slim for AngularJS

For example we want to use templating Slim in AngularJS app. Let our templates will be in app/assets/webapp/. We make the following settings:

# config/application.rb
config.assets.paths << Rails.root.join('app', 'assets', 'webapp')

# config/initizlizers/assets_engine.rb
Rails.application.assets.register_engine('.slim', Slim::Template)

# config/environments/production.rb
config.assets.precompile += ['*.html']

Do not forget to connect a file in your application.js

//= require app_assets

Now for the template app/assets/webapp/blogs/edit.html.slim we can get a path depending on the environment:

var path = asset_path('blogs/edit.html')

// the function will return for development:
// /assets/blogs/edit.html

// and for production
// /assets/blogs/edit-5eb3bb250d5300736006c8944e436e3f.html

$routeProvider
    .when('/books', {
    templateUrl: assetPath('bookOverview.html'),
    controller: BooksOverviewCtrl 
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.