Angularjs - NgView not working

Here is the basic setup, which has a default noemployee.html partial: as the ng-view

enter image description here

Index.html content:

 <div id="container" ng-controller="EmployeeCtrl">

 <!-- Side Menu -->
 <span id="smenuSpan">
 <ul id="thumbList">
 <li ng-repeat="employee in employees | filter:categories">
 <a href="Employee/{{employee.id}}"><img  class="smallImage" ng-src="content/app/images/{{employee.image}}" alt="{{employee.description}}"></a>
 </li>
 </ul>
 </span>

 <!-- Content -->
 <span id="contentSpan">
 <div ng-view></div>    
 </span>

 </div>

My Route Provider:

var EmployeeModule = angular.module('EmployeeModule',  [], function($routeProvider, $locationProvider) {

$routeProvider.when('/', { templateUrl: 'content/app/partials/noemployee.html', controller: EmployeeModule.EmployeeCtrl });
$routeProvider.when('Employee/:id', { templateUrl: 'content/app/partials/employee.html', controller: EmployeeModule.EmployeeCtrl });
$routeProvider.otherwise({ redirectTo: '/' });

$locationProvider.html5Mode(true);

My Controller:

function EmployeeCtrl($scope, $http, $routeParams, $timeout) {

    $scope.employees = [
{ "id": 1, "category": "ones", "image": "person1.jpg",  "description": "person 1 description", name:"Jane Smith" },
{ "id": 2, "category": "twos", "image": "person2.jpg", "description": "person 2 description", name: "Mark Sharp" },
{ "id": 3, "category": "threes", "image": "person3.jpg", "description": "person 3 description", name: "Kenny Suave" },
{ "id": 4, "category": "fours", "image": "person4.jpg", "description": "person 4 description", name: "Betty Charmer" },
{ "id": 5, "category": "fives", "image": "person5.jpg", "description": "person 5 description", name: "John Boss" }
];

$scope.employeesCategories = [];
$scope.currentEmployee = {};
$scope.params = $routeParams;

$scope.handleEmployeesLoaded = function (data, status) {
    //$scope.images = data;
    // Set the current image to the first image in images
    $scope.currentEmployee = _.first($scope.employees);
    // Create a unique array based on the category property in the images objects
    $scope.employeeCategories = _.uniq(_.pluck($scope.employees, 'category'));
}

$scope.fetch = function () {
    $http.get($scope.url).success($scope.handleEmployeesLoaded);
};

$scope.setCurrentEmployee = function (employee) {
    $scope.currentEmployee = employee;
};

// Defer fetch for 1 second to give everything an opportunity layout
$timeout($scope.fetch, 1000);

}

Observations:

  1. At present, if I click on any employee, no 'Employee/??' is added to the address bar path [ which isn't a crime to me], however, the main content div does not change the partial to the employee.html.

  2. If I comment out "$locationProvider.html5Mode(true);", the default localhost is now "http://localhost:31219/#/" and when I click on any employee the address bar shows 'http://localhost:31219/Employee/1', and the page is navigated away to a 404 error page.

I know I am bastardizing something here that the solution is so simple it escapes me.

Goals:

  1. I really would like to avoid hash tags in my address bar.
  2. It would be nice but no req that the employee/id not show up in the address bar but I suspect the partial cannot change w/o it. and, naturally

  3. I want the partial to change to the 'employee.html" page when an employee is clicked.

Does anyone see where I am going wrong with this code?

Thanks in Advance!

Solution:

  1. I needed to put '#/' in the img href --> href="#/Employee/{{employee.id}}"
  2. Comment out '$locationProvider.html5Mode(true);'

As a side note, I sure wish I knew how to get this to work w/o those pesky hash tags. Any ideas anyone?

In order to use html5mode, your server has to serve up the main app index file for otherwise invalid routes.

So, for example, if your server side code handles CRUD operations on paths like: /api/employees, /api/employees/:id, etc...

and it serves up static content, images, html, css, js, etc.

For any other request, that would otherwise be a 404, it should, instead of responding with a 404, respond with a 200 code, and serve up the index.html file.

This way any non static and non server side route gets handled by the angular app.

This is mentioned in the Angular guide on this page: http://docs.angularjs.org/guide/dev_guide.services.$location

Note the 'server side' comment at the end:

Html link rewriting

When you use HTML5 history API mode, you will need different links in different browsers, but all you have to do is specify regular URL links, such as: <a href="/some?foo=bar">link</a>

When a user clicks on this link:

In a legacy browser, the URL changes to /index.html#!/some?foo=bar

In a modern browser, the URL changes to /some?foo=bar In cases like the following, links are not rewritten; instead, the browser will perform a full page reload to the original link.

Links that contain target element Example: <a href="/ext/link?a=b" target="_self">link</a>

Absolute links that go to a different domain Example: <a href="http://angularjs.org/">link</a>

Links starting with '/' that lead to a different base path when base is defined
Example: <a href="/not-my-base/link">link</a>

Server side

Using this mode requires URL rewriting on server side, basically you have to rewrite all your links to entry point of your application (e.g. index.html)

This was the problem:

<a href="Employee/{{employee.id}}"><img  class="smallImage" ng-src="content/app/images/{{employee.image}}" alt="{{employee.description}}"></a>

Solution:

  1. I needed to put '#/' in the img href --> href="#/Employee/{{employee.id}}"
  2. Comment out '$locationProvider.html5Mode(true);'

As a side note, I sure wish I knew how to get this to work w/o those pesky hash tags. Any ideas anyone?