1

I'm new to angularjs/clientjs and would like to consume a rails json api with angularjs. After some research I wrote the ff: code but when I visit http://localhost:3000/users I get plain json. Angularjs is not being called to render a view.

How can I render an angularjs view that formats and shows the data a rails json api returns?

rails/routes

app::Application.routes.draw do
  get 'main/index' => 'main#index'
  resources :users, defaults: {format: :json}
end

rails/users_controller.rb

def index
 @users = User.all
end

rails/main_controller.rb

def index
 # blank
end

rails/application layout

..
<html ng-app='gold'>
..
<div ng-view>
  <%= yield %>
</div>
..

app/assets/templates/main/index.html

app/assets/templates/users/index.html

app/assets/javascripts/main.js

var myApp = angular.module('gold', ['ngRoute', 'ngResource']);

myApp.config(function($routeProvider, $locationProvider, $httpProvider) {
    console.log("in router")
    $httpProvider.defaults.headers.common['X-CSRF-Token'] = 
    $('meta[name=csrf-token]').attr('content');
    $locationProvider.html5Mode(true);
    $routeProvider.
        when('/users', {
            templateUrl: '../assets/users/index.html',          
            controller: 'UsersController'
        }).when('/main/index', {
            templateUrl: '../assets/main/index.html',
            controller: 'MainController'
        }).otherwise({
            redirectTo: '/'
        });
});

app/assets/javascripts/services/UserService.js

myApp.factory('UserService', ['$resource', function($resource) {
console.log("in user service")
return $resource('/users/:id', {id: '@id'}, {
    index: { method: 'GET', isArray: true },
    create: { method: 'POST' },
    show: { method: 'GET' },
    update: { method: 'PUT', params: {id: '@id'} }
    //delete: { method: 'DELETE', params: {id: '@id'} }
});
}]);

app/assets/javascripts/controllers/UsersController.js

myApp.controller('UsersController', ['$scope', 'UserService', function($scope, UserService) {
 console.log("in user controller")
   $scope.users = UserService.query();
}]);
LightBox
  • 3,395
  • 4
  • 25
  • 38
  • What is your question? – Peter Brown Apr 10 '14 at 18:15
  • I edited it out accidentally. Still I thought it was obvious. Angularjs templates are not being called. Neither are rails templates. Just json. – LightBox Apr 10 '14 at 18:19
  • You're specifying the default format to be json in your routes.rb for /users. If you don't want that to be the case, why is it there? If you want the default format to be HTML, just remove it. Otherwise, you should be able to add .html to the end of the URL. – Peter Brown Apr 10 '14 at 18:24
  • I'm not sure I understand you. I would like the rails app to send json to the angularjs client. The angularjs client would then use the json data to render a angular html template. Is this how angular works? I'm new to this. I assumed I should not use rails templates at all but some tutorials have been using rails templates along with angular templates. Should I just delete the rails view directory? – LightBox Apr 10 '14 at 18:29
  • I too have a similar issue. Is the above issue resolved ? Can any one help ? – Rajasree Muraleedharan Dec 03 '15 at 06:26

1 Answers1

0

I think I know what you are trying, as I'm working on similar problem.

  1. Once Rails sends json, that is it. You can't ask it to render other html/erb and use it to interpret the json data.
    see this answer on How can we use rails routes with angularjs in a DRY way?

  2. To achieve both Rails + Angular routing at the same time (render Rails pages with URL, json data with ajax/api calls), I have setup a @view model contains Angular page url for the request + json data.

For a normal HTML request: default.html.erb translates the @view variable to .js using a "jsonService.js.erb", and render the angular page in @view.

For ajax/api calls: Setup routes using angular.config as you did for render page, and add resolve: fetchData(controller#action) to fetch the json data from Rails controllers and use it in the angular page.

Rails Controller:
respond_to do |format|
  format.json { @view }
  format.html { render 'layouts/default' }
end
default.html.erb
<script id="jsonService"><%= render "layouts/json_service.js" %></script>
<div ng-include ="content.view.template"></div>
Angular

You can use what you got for angular.config. Just remember to use ng-href or ng-click for the links in json/api calls.

if you have dynamic routing in the angular.config, remember to call $scope.$digest after you replaced the html content.

Community
  • 1
  • 1
Jie Cai
  • 51
  • 6
  • What I actually wanted to do was the standard angularjs use case. I needed to route all incoming server requests to bypass the rails router and go to angularjs routes. I used `root to: application#home' get "*path" => "application#home"`. Then in that controller I put in `render :layout => 'application', :nothing => true` since no server side view is rendered. – LightBox May 21 '14 at 17:41
  • If you asked Rails to render nothing, then how do you get the user data into your view? Say if it is a single page site/or api service, you can render the json with js/json calls (Rails controller still need to render :json @user, otherwise there is nothing returned). Then the index page/client app will need to pre-load with the angular scripts before first json call. which means index page can't be json. you can take a look this – Jie Cai May 22 '14 at 11:10
  • Try use Rails to render html + angular script for "/" and use angular.config to handle the rest of routing. – Jie Cai May 22 '14 at 23:06