title: AngularJS with Laravel failed to instantiate module app
body: <p>I'm using Laravel 4.2 and angular 1.2.21. I've followed this tutorial: <a href="http://scotch.io/tutorials/php/create-a-laravel-and-angular-single-page-comment-application" rel="nofollow">http://scotch.io/tutorials/php/create-a-laravel-and-angular-single-page-comment-application</a>, but I've run into a strange error. I'm also using Browserify and gulp to organize my dependencies. The error doesn't appear to be with gulp or Browserify, as I've been able to confirm that the compiled js file has everything.</p>
  
  <p>My routing appears to be okay, my database has data (successfully populated on my api/food_item_templates route), and the food_item_templates/index view loads, but I am getting a js error when angular tries to instantiate one of my modules.</p>
  
  <p>The error I'm getting is:</p>
  
  <pre><code>Uncaught Error: [$injector:modulerr] Failed to instantiate module app due to:
  Error: [$injector:modulerr] Failed to instantiate module {"_invokeQueue":[["$controllerProvider","register",{"0":"mainController"}]],"_runBlocks":[],"requires":[],"name":...&lt;omitted&gt;...2)
  </code></pre>
  
  <p><strong>app/views/layouts/angular.blade.php</strong></p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html lang="en"&gt;
  &lt;head&gt;
      &lt;meta charset="utf-8"&gt;
      &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
      &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
      &lt;meta name="description" content=""&gt;
      &lt;meta name="author" content=""&gt;
      &lt;link rel="shortcut icon" href="../../assets/ico/favicon.ico"&gt;
  
      &lt;title&gt;Test&lt;/title&gt;
  
  &lt;/head&gt;
  
  &lt;body ng-app="app" ng-controller="mainController"&gt;
  
  @yield('content')
  
  &lt;script src="/js/main.js"&gt;&lt;/script&gt;
  
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p><strong>routes.php</strong></p>
  
  <pre><code>Blade::setContentTags('&lt;%', '%&gt;');      // for variables and all things Blade
  Blade::setEscapedContentTags('&lt;%%', '%%&gt;');     // for escaped data
  
  ...
  
  Route::get('food_item_templates', function() {
      return View::make('food_item_templates/index');
  });
  
  Route::group(array('prefix' =&gt; 'api'), function() {
      Route::resource('food_item_templates', 'FoodItemTemplatesController',
          array('only' =&gt; array('index', 'store', 'destroy')));
  });
  </code></pre>
  
  <p><strong>app/views/food_item_templates/index.blade.php</strong></p>
  
  <pre><code>@extends('layouts.angular')
  
  @section('content')
  &lt;div class="food_item_template" ng-hide="loading" ng-repeat="food_item_template in food_item_templates"&gt;
      &lt;h3&gt;Food Item Template #{{ food_item_template.id }} &lt;small&gt;by {{ food_item_template.name }}&lt;/h3&gt;
      &lt;p&gt;{{ food_item_template.text }}&lt;/p&gt;
  
      &lt;p&gt;&lt;a href="#" ng-click="deleteFoodItemTemplate(food_item_template.id)" class="text-muted"&gt;Delete&lt;/a&gt;&lt;/p&gt;
  &lt;/div&gt;
  @stop
  </code></pre>
  
  <p><strong>app/javascript/controllers/mainCtrl.js</strong></p>
  
  <pre><code>'use strict';
  
  module.exports = angular.module('mainCtrl', [])
  
      .controller('mainController', function($scope, $http, FoodItemTemplate) {
          $scope.foodItemTemplateData = {};
  
          $scope.loading = true;
  
          FoodItemTemplate.get()
              .success(function(data) {
                  $scope.foodItemTemplates = data;
                  $scope.loading = false;
              });
  
          $scope.submitFoodItemTemplate = function() {
              $scope.loading = true;
  
              FoodItemTemplate.save($scope.foodItemTemplateData)
                  .success(function(data) {
  
                      FoodItemTemplate.get()
                          .success(function(getData) {
                              $scope.foodItemTemplates = getData;
                              $scope.loading = false;
                          });
  
                  })
                  .error(function(data) {
                      console.log(data);
                  });
          };
  
          $scope.deleteFoodItemTemplate = function(id) {
              $scope.loading = true;
  
              FoodItemTemplate.destroy(id)
                  .success(function(data) {
  
                      FoodItemTemplate.get()
                          .success(function(getData) {
                              $scope.foodItemTemplates = getData;
                              $scope.loading = false;
                          });
  
                  });
          };
  
      });
  </code></pre>
  
  <p><strong>app/javascript/services/foodItemTemplateService.js</strong></p>
  
  <pre><code>'use strict';
  
  module.exports = angular.module('foodItemTemplateService', [])
  
      .factory('FoodItemTemplate', function($http) {
  
          return {
              get : function() {
                  return $http.get('/api/food_item_templates');
              },
  
              save : function(foodItemTemplateData) {
                  return $http({
                      method: 'POST',
                      url: '/api/food_item_templates',
                      headers: { 'Content-Type' : 'application/x-www-form-urlencoded' },
                      data: $.param(foodItemTemplateData)
                  });
              },
  
              destroy : function(id) {
                  return $http.delete('/api/food_item_templates/' + id);
              }
          }
  
      });
  </code></pre>
  
  <p><strong>app/javascript/main.js</strong></p>
  
  <pre><code>'use strict';
  
  var angular         = require('angular');
  var mainCtrl        = require('./controllers/mainCtrl');
  var foodItemTemplateService = require('./services/foodItemTemplateService');
  
  angular.module('app', [mainCtrl, foodItemTemplateService]);
  </code></pre>
  
  <p><strong>gulpfile.js</strong></p>
  
  <pre><code>...
  
  gulp.task('scripts', function() {
      gulp.src('app/javascript/main.js')
          .pipe(browserify({
            insertGlobals : true,
            debug : !gulp.env.production
          }))
          .pipe(gulp.dest('./public/js'))
  });
  
  gulp.task('watch', function() {
      gulp.watch('app/javascript/**/*.js', ['scripts'])
  });
  
  gulp.task('default', ['scripts']);
  </code></pre>
  
  <p><strong>package.json</strong></p>
  
  <pre><code>{
  
  ...
  
    "main": "gulpfile.js",
    "directories": {
      "test": "tests"
    },
    "dependencies": {
      "angular": "^1.2.21",
      "gulp": "^3.8.7"
    },
    "devDependencies": {
      "gulp": "^3.8.7",
      "gulp-browserify": "^0.5.0",
      "gulp-compass": "^1.3.1",
      "gulp-concat": "^2.3.4",
      "gulp-jshint": "^1.8.4",
      "gulp-notify": "^1.5.0",
      "gulp-phpspec": "^0.2.5",
      "gulp-rename": "^1.2.0",
      "gulp-sass": "^0.7.3",
      "gulp-uglify": "^0.3.1",
      "gulp-util": "^3.0.0"
    },
    "scripts": {
      "test": "echo \"Error: no test specified\" &amp;&amp; exit 1"
    },
  
  }
  </code></pre>