I'm following the UI-Router Nested States & Nested Views : Abstract State code example from https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views#abstract-states and adapting it to my ExpressJS (Jade template) app.
When I type in http://localhost:3030/#/contacts
and press enter, the contacts
portion of the URL gets deleted leaving the URL as http://localhost:3030/#/
.
But if I add an extra /
to the end of the URL like http://localhost:3030/#/contacts/
that will work and I will see
Also, if I go to http://localhost:3030/#/contacts/list
then I will see
- the
contacts.jade
template display properly in theui-view
of thelayout.jade
template - the
contacts-list.jade
(Alice & Bob) display properly inui-view
of thecontacts.jade
template
And then if I click on the Alice link I will see
So I'm not sure why I can't access the /contacts
URL. Below are all relevant files.
AngularJS / UI-Router
app.js
'use strict';
var app = angular.module('app', ['ui.router']);
app.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('contacts', {
abstract: true,
url: '/contacts',
templateUrl: '/partials/contacts',
controller: function($scope){
$scope.contacts = [{id: 0, name: "Alice"}, {id: 1, name: "Bob"}];
}
})
.state('contacts.list', {
url: '/list',
templateUrl: '/partials/contacts-list'
})
.state('contacts.detail', {
url: '/:id',
templateUrl: '/partials/contacts-detail',
controller: function($scope, $stateParams){
$scope.person = $scope.contacts[$stateParams.id];
}
})
}]);
Jade templates
index.jade
extends ../views/includes/layout
layout.jade
doctype html
html
include head
body(ng-app='app')
<div ui-view></div>
include scripts
contacts.jade
h1 Contacts
<div ui-view></div>
contacts-list.jade
ul
li(ng-repeat="person in contacts")
a(ng-href="#/contacts/{{person.id}}") {{person.name}}
contacts-detail.jade
h2 {{person.name}}
ExpressJS
server.js
var express = require('express'),
mongoose = require('mongoose'),
morgan = require('morgan'),
bodyParser = require('body-parser'),
path = require('path');
var env = process.env.NODE_ENV = process.env.NODE_ENV || 'development';
var app = express();
// configuration
app.set('views', path.join(__dirname, '/app/views'));
app.set('view engine', 'jade');
app.use(morgan('dev')); // logs every request to console
app.use(bodyParser()); // pull information from html in POST
app.use(express.static(__dirname + '/public'));
// connect to mongodb via mongoose
if(env === 'development') {
mongoose.connect('mongodb://localhost/3lf');
} else {
mongoose.connect('mongodb://maxmythic:[email protected]:33307/3lf');
}
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error ...'));
db.once('open', function(callback) {
console.log('3lf db is open for business ...');
});
// create mongoose schema and retrieve data
var messageSchema = mongoose.Schema({message: String});
var Message = mongoose.model('Message', messageSchema);
var mongoMessage;
Message.findOne().exec(function(err, messageDoc){
mongoMessage = messageDoc.message;
});
// define routes
// make sure to coordinate client side and server side routes
app.get('/partials/:partialPath', function(req, res) {
res.render('partials/' + req.params.partialPath);
});
app.get('*', function(req, res) {
res.render('index', {
mongoMessage: mongoMessage
});
});
var port = process.env.PORT || 3030;
app.listen(port);
console.log('Listening on port ' + port + '...');