PeteGO
PeteGO

Reputation: 5791

Simple Angular SPA in ASP .NET 5 - getting blank page on startup

I'm attempting to set up a very simple Angular single-page-application in ASP .NET 5. I've begun with an empty project - the only angular dependency at the moment is ngRoute.

The problem:

When I run the project, I get a blank page in my browser - with no errors in the developer console.

EDIT

I removed the [] from the angular.module('app', []).controller as suggested but now an error is thrown:

Uncaught Error: [$injector:modulerr] Failed to instantiate module app due to: Error: [$injector:unpr] Unknown provider: a

I'm using npm, bower, and grunt - but I don't think they have anything to do with the problem.

Here's what the project structure looks like:

enter image description here

Here's the index.html:

<!DOCTYPE html>
<html ng-app="app">
<head>
    <meta charset="utf-8" />
    <title></title>
    <!-- angular -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-rc.0/angular.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-rc.0/angular-route.js"></script>
    <!-- app -->
    <script src="app.js"></script>
</head>
<body ng-cloak>
    <div ng-view>
    </div>
</body>
</html>

Here's the app.js:

(function () {
    'use strict';

    var app = angular.module('app', ['ngRoute']);

    app.config(function ($routeProvider) {
        $routeProvider
            .when('/', {
                templateUrl: 'Views/home.html',
                controller: 'home'
            })
            .otherwise({
                redirectTo: '/'
            });
    });
})();

Here's the home.js:

(function () {
    'use strict';
    angular.module('app').controller('home', function controller($scope) {
        $scope.title = 'Home';
    });
})();

Here's the home.html:

<div ng-controller="home">
    {{ title }}
</div>

Why do I get a blank page and not the text "Home" rendered on screen?

The app.js under wwwroot contains all of the contents of the Scripts folder - with the app.js contents written first. Here's the gruntfile.js:

module.exports = function (grunt) {
    // Load grunt plugins from npm.
    grunt.loadNpmTasks("grunt-contrib-uglify");
    grunt.loadNpmTasks("grunt-contrib-watch");

    // Configure plugins.
    grunt.initConfig({
        // Combine and minify all of the javascript files from the Scripts folder into the wwwroot 
        // folder, making sure the app.js is placed at the beginning.
        uglify: {
            my_target: {
                files: { "wwwroot/app.js": ["Scripts/App/app.js", "Scripts/**/*.js"] }
            }
        },

        // Re-run the uglify task when any of the files in the Scripts folder change.
        watch: {
            scripts: {
                files: ["Scripts/**/*.js"],
                tasks: ["uglify"]
            }
        }
    });

    // Define tasks.
    grunt.registerTask("default", ["uglify", "watch"]);
};

I can see that the angular.js, angular-route.js, and app.js have loaded correctly in the browser. Here's the contents of the "uglified" app.js:

!function(){"use strict";var a=angular.module("app",["ngRoute"]);a.config(function(a){a.when("/",{templateUrl:"Views/home.html",controller:"home"}).otherwise({redirectTo:"/"})})}(),function(){"use strict";angular.module("app",[]).controller("home",function(a){a.title="Home"})}();

Upvotes: 1

Views: 1239

Answers (2)

rzelek
rzelek

Reputation: 4023

Claies is right when it comes to app initialization, but there is another thing.

You problem is much more complicated than you think. You are using uglifyjs, which changes names of variables in controller arguments. You need to use ngannotate in gruntfile.js or switch to longer controller definition.

This is brief explanation: uglify wants to make your JS files lighter and changes it from this:

myApp.controller('GreetingController', function($scope, service) {
  $scope.greeting = 'Hola!';
  service.fnc();
});

To this:

myApp.controller('GreetingController', function(a,b) {
  a.greeting = 'Hola!';
  b.fnc();
});

This causes problems for angular because it does not know what a is.

If you want to solve it without changing your controllers, you can use ngannotate task. Alternative way is changing controller's definition:

myApp.controller('GreetingController', ['$scope', 'service', function($scope, service) {
  $scope.greeting = 'Hola!';
  service.fnc();
}]);

Uglify will transform that to:

myApp.controller('GreetingController', ['$scope', 'service', function(a, b) {
  a.greeting = 'Hola!';
  b.fnc();
}]);

NOTE: Please have in mind that using ngannotate is probably better way, beacause you will not face same problems with 3rd party services etc.

Upvotes: 5

Claies
Claies

Reputation: 22323

Your home.js has a subtle bug. You are re-declaring your app module, which is removing all the route configuration.

angular.module('app', []).controller... is the setter syntax for a module. Instead, you should use angular.module('app').controller getter syntax, to avoid re-declaring the module.

Upvotes: 2

Related Questions