1

I'm following along with the Angular/Rails tutorial at Thinkster and I've run into an issue which seems to be most likely be Angular-related. Everything works just fine until I get to the Angular Routing section. Simply put, the inline templates within the <script> tags do not load in the <ui-view></ui-view> element. I originally thought this may be due to having opened the page locally as a file rather than having it loaded from a server, but the same problem persists even after integrating Rails (using an older version of Sprockets, as pointed out in this similar but unrelated issue).

When I load the index page in either the browser as a file or as a URL when running the Rails server, I've inspected the HTML and, sure enough, the only thing it shows in the code are the divs and an empty <ui-view> element, indicating something just isn't adding up correctly. I've tried various things, including:

  • Using the newest version of ui-router (0.2.15 at this writing) rather than the version in the tutorial
  • Using <div ui-view></div> instead of <ui-view></ui-view>
  • Changing the value of 'url' in the home state to 'index.html', including using the full path to the file (file:///...)
  • Putting the contents of the inline <script> templates into their own files (without the <script> tags, of course) and specifying the 'templateUrl' field using both relative and full paths
  • Trying both Chrome and Firefox just to be extra certain

None of these things have worked, even when accessing http://localhost:3000/#/home when the Rails server is running after having integrated Angular into the asset pipeline in the Integrating the Front-end with the Asset Pipeline section of the tutorial. Indeed, the route loads but does not show anything more than a completely blank page with a lonesome and empty <ui-view> element when inspecting the HTML using Chrome's dev tools.

Given that the issue seems to occur even before the Rails portion, it does seem like something to do with Angular itself, but I've got no clue what's going on, especially since I've followed along to the letter.

I'm using Bower to manage the Angular dependencies and the HTML does show that the Angular javascript files in both the app/assets/javascripts directory and in the vendor/assets/bower_components directory are being loaded properly in the <head> section, so everything seems to be okay on the asset pipeline integration.

Versios I'm using:
Rails: 4.2.3
Ruby: 2.2.1p85
Angular: 1.4.3
ui-router: 0.2.15

The code I've got for the major moving parts is below:

app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
<head>
  <title>Test App</title>
  <%= stylesheet_link_tag    'application', media: 'all' %>
  <%= javascript_include_tag 'application' %>
  <%= csrf_meta_tags %>
</head>
<body ng-app="testApp">
  <div class="row">
    <div class="col-md-6 col-md-offset-3">
      <ui-view></ui-view>
    </div>
  </div>
</body>
</html>

app/assets/javascripts/app.js

angular.module('testApp', ['ui.router', 'templates']).config(['$stateProvider', '$urlRouteProvider', function($stateProvider, $urlRouteProvider) {
  $stateProvider
    .state('home', {
      'url': '/home',
      'templateUrl': 'home/_home.html',
      'controller': 'MainCtrl'
    })
    .state('posts', {
      'url': '/posts/{id}',
      'templateUrl': 'posts/_posts.html',
      'controller': 'PostsCtrl'
    });

  $urlRouteProvider.otherwise('home');
}]);

app/assets/javascripts/application.js

//= require angular
//= require angular-rails-templates
//= require angular-ui-router
//= require_tree .

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  respond_to :json

  def angular
    render 'layouts/application'
  end
end

config/routes.rb

Rails.application.routes.draw do
  root to: 'application#angular'
end

app/assets/javascripts/home/mainCtrl.js

angular.module('testApp').controller('MainCtrl', ['$scope', 'posts', function($scope, posts) {
  $scope.posts = posts.posts;

  $scope.addPost = function() {
    if (!$scope.title || $scope.title === "")
      return;

    $scope.posts.push({
      'title': $scope.title,
      'link': $scope.link,
      'upvotes': 0,
      'comments': [
        {'author': 'Some Person', 'body': 'This is a comment.', 'upvotes': 0},
        {'author': 'Another Person', 'body': 'This is also a comment.', 'upvotes': 0}
      ]
    });

    $scope.title = "";
    $scope.link = "";
  };

  $scope.incrementUpvotes = function(post) {
    post.upvotes++;
  };
}]);

app/assets/javascripts/posts/postsCtrl.js

angular.module('testApp').controller('PostsCtrl', ['$scope', '$stateParams', 'posts', function($scope, $stateParams, posts) {
  $scope.post = posts.posts[$stateParams.id];

  $scope.addComment = function() {
    if($scope.body === '')
      return;

    $scope.post.comments.push({
      'body': $scope.body,
      'author': 'user',
      'upvotes': 0
    });

    $scope.body = '';
  };
}]);

app/assets/javascripts/posts/posts.js

angular.module('testApp').factory('posts', ['$http', function($http) {
  var o = {
    'posts': []
  };

  o.getAll = function() {
    return $http.get('/posts.json').success(function(data) {
      angular.copy(data, o.posts);
    });
  };

  return o;
}]);

If any other code is required to help uncover the problem, please let me know and I'll supply anything requested.

Community
  • 1
  • 1
  • inspect the ajax requests being made for templates in browser dev tools network. Are they being made? Are paths correct? You mention having your templates in script tags but none are shown so angular will call for them on server – charlietfl Jul 25 '15 at 13:42
  • Apologies for any confusion: in the earlier part of the tutorial the templates are in script tags on the main index.html page, but these are later moved to files of their own (the _posts.html and _home.html partials). Given that app.js is in app/assets/javascripts, the paths to the templates in the Angular routes appear to be correct (e.g. 'home/_home.html'). To that point, however, I see no XHR requests when the page loads, so that does seem to be the issue that I can't pinpoint. All the scripts are loaded successfully (200 status), but no Ajax to be seen. –  Jul 25 '15 at 13:52
  • one thing is definite...must open page from server, not from file since ajax is restricted on file protocol. Should be seeing XHR requests for those templates. Any errors thrown in console? – charlietfl Jul 25 '15 at 14:07
  • I do see several "Module 'testApp' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument" errors. The module name is consistently "testApp" for all of the modules, so there are at least no misspellings. Additionally, it does appear that angular-rails-templates is working correctly, as it's loading the partials as scripts like it should, e.g. angular.module("templates").run(["$templateCache", function($templateCache) { ... . So, it seems to boil down to those uncaught exceptions. –  Jul 25 '15 at 14:18
  • Well that's the critical part. Replace the view files above with angular code used. That exception can also be caused by a syntax error anywhere in your module code – charlietfl Jul 25 '15 at 14:22
  • Views have been removed and the code for the posts factory and the two controllers has been added in its place. –  Jul 25 '15 at 14:44
  • 1
    Nothing jumps out at me. Visual inspection syntax all looks clean. That module error will get thrown though if anything is broken within the module. Also note if using minified version of angular you get more verbose error and stack trace output using development version – charlietfl Jul 25 '15 at 15:22
  • I was thankfully using the dev version so I did peer over the stack trace. I found my error: it's supposed to be $urlRouterProvider, I had it as $urlRouteProvider. And to think if I'd check the console prior... stupid mistakes, but all is good now. Thanks for your help! –  Jul 25 '15 at 16:43

2 Answers2

3

it seems that the angular-ui-router is incompatible with the new Rails sprockets. To fix this, add this earlier version of sprockets to your gemfile:

gem 'sprockets', '2.12.3'

And then run bundle update sprockets.

This was answered a few times in other similar questions, like the one below: Angular Rails Templates just not working

Community
  • 1
  • 1
Sia
  • 8,894
  • 5
  • 31
  • 50
0

$urlRouteProvider in my code should've been $urlRouterProvider. Be sure to double-check everything, folks, and make good use of the console!