我是MEAN Stack Web Development的初学者,并且一直在研究mean-stack-tutorial。我已经通过身份验证用户来到最后一节了,一切似乎都运行良好(在任何地方都没有控制台错误,而且功能齐全)但是,在index.ejs文件的MainCtrl
中,post.author表达式即使我登录并提交帖子(而不是ng-show="post.author"
阻止它显示),我也没有评估。
angularApp.js - 我在这里编辑了MainCtrl
中的posts.create函数以包含作者。 auth.currentUser()
确实在此控制器中正确评估(使用console.log(auth.currentUser());
中的$scope.incrementUpvotes
函数中的MainCtrl
进行了测试。)
var app = angular.module('flapperNews', ['ui.router']);
app.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/home.html',
controller: 'MainCtrl',
resolve: {
postPromise: ['posts', function(posts) {
return posts.getAll();
}]
}
})
.state('posts', {
url: '/posts/{id}',
templateUrl: '/posts.html',
controller: 'PostsCtrl',
resolve: {
post: ['$stateParams', 'posts', function($stateParams, posts) {
return posts.get($stateParams.id);
}]
}
})
.state('login', {
url: '/login',
templateUrl: '/login.html',
controller: 'AuthCtrl',
onEnter: ['$state', 'auth', function($state, auth){
if(auth.isLoggedIn()){
$state.go('home');
}
}]
})
.state('register', {
url: '/register',
templateUrl: '/register.html',
controller: 'AuthCtrl',
onEnter: ['$state', 'auth', function($state, auth){
if(auth.isLoggedIn()){
$state.go('home');
}
}]
});
$urlRouterProvider.otherwise('home');
}])
.factory('auth', ['$http', '$window', function($http, $window){
var auth = {};
auth.saveToken = function(token) {
$window.localStorage['flapper-news-token'] = token;
};
auth.getToken = function (){
return $window.localStorage['flapper-news-token'];
};
auth.isLoggedIn = function(){
var token = auth.getToken();
if(token){
var payload = JSON.parse($window.atob(token.split('.')[1]));
return payload.exp > Date.now() / 1000;
} else {
return false;
}
};
auth.currentUser = function(){
if(auth.isLoggedIn()){
var token = auth.getToken();
var payload = JSON.parse($window.atob(token.split('.')[1]));
return payload.username;
}
};
auth.register = function(user) {
return $http.post('/register', user).success(function(data) {
auth.saveToken(data.token);
});
};
auth.logIn = function(user){
return $http.post('/login', user).success(function(data){
auth.saveToken(data.token);
});
};
auth.logOut = function(){
$window.localStorage.removeItem('flapper-news-token');
};
return auth;
}])
.controller('AuthCtrl', [
'$scope',
'$state',
'auth',
function($scope, $state, auth){
$scope.user = {};
$scope.register = function(){
auth.register($scope.user).error(function(error){
$scope.error = error;
}).then(function(){
$state.go('home');
});
};
$scope.logIn = function(){
auth.logIn($scope.user).error(function(error){
$scope.error = error;
}).then(function(){
$state.go('home');
console.log(auth.currentUser());
});
};
}])
app.factory('posts', ['$http', 'auth', function($http, auth){
var o = {
posts: []
};
o.getAll = function() {
return $http.get('/posts').success(function(data){
angular.copy(data, o.posts);
});
};
o.get = function(id) {
return $http.get('/posts/' + id).then(function(res){
return res.data;
});
};
o.create = function(post) {
return $http.post('/posts', post, {
headers: {Authorization: 'Bearer '+auth.getToken()}
}).success(function(data){
o.posts.push(data);
});
};
o.upvote = function(post) {
return $http.put('/posts/' + post._id + '/upvote', null, {
headers: {Authorization: 'Bearer '+auth.getToken()}
}).success(function(data){
post.upvotes += 1;
});
};
o.addComment = function(id, comment) {
return $http.post('/posts/' + id + '/comments', comment, {
headers: {Authorization: 'Bearer '+auth.getToken()}
});
};
o.upvoteComment = function(post, comment) {
return $http.put('/posts/' + post._id + '/comments/'+ comment._id + '/upvote', null, {
headers: {Authorization: 'Bearer '+auth.getToken()}
}).success(function(data){
comment.upvotes += 1;
});
};
return o;
}]);
app.controller('MainCtrl', [
'$scope', 'posts', 'auth',
function($scope, posts, auth){
$scope.test = 'Hello world!';
$scope.posts = posts.posts;
$scope.isLoggedIn = auth.isLoggedIn;
$scope.addPost = function() {
if(!$scope.title || $scope.title === '') { return; }
posts.create({
title: $scope.title,
author: auth.currentUser(),
link: $scope.link,
});
$scope.title = '';
$scope.link = '';
};
$scope.incrementUpvotes = function(post) {
posts.upvote(post);
console.log(auth.currentUser())
};
}])
app.controller('PostsCtrl', [
'$scope',
'$stateParams',
'posts',
'post',
'auth',
function($scope, $stateParams, posts, post, auth){
$scope.post=post;
$scope.isLoggedIn = auth.isLoggedIn;
$scope.addComment = function(){
if($scope.body === '') { return; }
posts.addComment(post._id, {
body: $scope.body,
author: 'user',
}).success(function(comment) {
$scope.post.comments.push(comment);
});
}
$scope.addUpvote = function(comment){
posts.upvoteComment(post, comment);
};
$scope.body = '';
}
])
.controller('NavCtrl', [
'$scope',
'auth',
function($scope, auth){
$scope.isLoggedIn = auth.isLoggedIn;
$scope.currentUser = auth.currentUser;
$scope.logOut = auth.logOut;
}]);
Posts.js - 我在这里编辑了猫鼬模型以包含作者。
var mongoose = require('mongoose');
var PostSchema = new mongoose.Schema({
title: String,
link: String,
author: String,
upvotes: {type: Number, default: 0},
comments: [{type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }]
});
PostSchema.methods.upvote = function(cb) {
this.upvotes += 1;
this.save(cb);
};
mongoose.model('Post', PostSchema);
index.js
var express = require('express');
var jwt = require('express-jwt');
var router = express.Router();
var auth = jwt({secret: 'SECRET', userProperty: 'payload'});
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
var mongoose = require('mongoose');
var passport = require('passport');
var Post = mongoose.model('Post');
var Comment = mongoose.model('Comment');
var User = mongoose.model('User');
router.post('/register', function(req, res, next){
if(!req.body.username || !req.body.password){
return res.status(400).json({message: 'Please fill out all fields'});
}
var user = new User();
user.username = req.body.username;
user.setPassword(req.body.password)
user.save(function (err){
if(err){ return next(err); }
return res.json({token: user.generateJWT()})
});
});
router.post('/login', function(req, res, next){
if(!req.body.username || !req.body.password){
return res.status(400).json({message: 'Please fill out all fields'});
}
passport.authenticate('local', function(err, user, info){
if(err){ return next(err); }
if(user){
return res.json({token: user.generateJWT()});
} else {
return res.status(401).json(info);
}
})(req, res, next);
});
router.get('/posts', function(req, res, next) {
Post.find(function(err, posts) {
if (err) { return next(err);}
res.json(posts);
});
});
router.post('/posts', auth, function(req, res, next) {
var post = new Post(req.body);
post.author = req.payload.username;
post.save(function(err, post){
if(err){ return next(err); }
res.json(post);
});
});
router.param('post', function(req,res,next,id) {
var query = Post.findById(id);
query.exec(function (err, post) {
if (err) { return next(err);}
if (!post) { return next(new Error('can\'t find post')); }
req.post = post;
return next();
});
});
router.param('comment', function(req,res,next,id) {
var query = Comment.findById(id);
query.exec(function (err, comment) {
if (err) { return next(err);}
if (!comment) { return next(new Error('can\'t find comment')); }
req.comment = comment;
return next();
});
});
router.get('/posts/:post', function(req,res) {
req.post.populate('comments', function(err,post) {
if (err) { return next(err); }
res.json(post);
});
});
router.put('/posts/:post/upvote', auth, function(req, res, next) {
req.post.upvote(function(err, post){
if (err) { return next(err); }
res.json(post);
});
});
router.post('/posts/:post/comments', auth, function(req, res, next) {
var comment = new Comment(req.body);
comment.post = req.post;
comment.author = req.payload.username;
comment.save(function(err, comment){
if(err){ return next(err); }
req.post.comments.push(comment);
req.post.save(function(err, post) {
if(err){ return next(err); }
res.json(comment);
});
});
});
router.put('/posts/:post/comments/:comment/upvote', auth, function(req, res, next) {
req.comment.upvote(function(err, comment){
if (err) { return next(err); }
res.json(comment);
});
});
module.exports = router;
index.ejs
<html>
<head>
<title>Flapper News</title>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script>
<script src="/javascripts/angularApp.js"></script>
<style> .glyphicon-thumbs-up { cursor:pointer } </style>
</head>
<body ng-app="flapperNews">
<nav class="navbar navbar-default pull-right" ng-controller="NavCtrl">
<ul class="nav navbar-nav">
<li ng-show="isLoggedIn()"><a>{{ currentUser() }}</a></li>
<li ng-show="isLoggedIn()"><a href="" ng-click="logOut()">Log Out</a></li>
<li ng-hide="isLoggedIn()"><a href="/#/login">Log In</a></li>
<li ng-hide="isLoggedIn()"><a href="/#/register">Register</a></li>
</ul>
</nav>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<ui-view></ui-view>
</div>
</div>
<script type="text/ng-template" id="/home.html">
<div class="page-header">
<h1>Flapper News</h1>
</div>
<div ng-repeat="post in posts | orderBy:'-upvotes'">
<span class="glyphicon glyphicon-thumbs-up"
ng-click="incrementUpvotes(post)"></span>
{{post.upvotes}}
<span style="font-size:20px; margin-left:10px;">
<a ng-show="post.link" href="{{post.link}}">
{{post.title}}
</a>
<span ng-hide="post.link">
{{post.title}}
</span>
<span ng-show="post.author">
posted by <a>{{post.author}}</a> |
</span>
</span>
<span>
<a href="#/posts/{{post._id}}">Comments</a>
</span>
</div>
<div ng-hide="isLoggedIn()">
<h3>You need to <a href="/#/login">Log In</a> or <a href="/#/register">Register</a> before you can add a post.</h3>
</div>
<form ng-submit="addPost()" ng-show="isLoggedIn()" style="margin-top:30px;">
<h3>Add a new post</h3>
<div class="form-group">
<input type="text"
class="form-control"
placeholder="Title"
ng-model="title"></input>
</div>
<div class="form-group">
<input type="text"
class="form-control"
placeholder="Link"
ng-model="link"></input>
</div>
<button type="submit" class="btn btn-primary">Post</button>
</form>
</script>
<script type="text/ng-template" id="/posts.html">
<div class="page-header">
<h3>
<a ng-show="post.link" href="{{post.link}}">
{{post.title}}
</a>
<span ng-hide="post.link">
{{post.title}}
</span>
</h3>
</div>
<div ng-repeat="comment in post.comments | orderBy:'-upvotes'">
<span class="glyphicon glyphicon-thumbs-up" ng-click="addUpvote(comment)"></span>
{{comment.upvotes}} - by {{comment.author}}
<span style="font-size:20px; margin-left:10px;">
{{comment.body}}
</span>
</div>
<div ng-hide="isLoggedIn()">
<h3>You need to <a href="/#/login">Log In</a> or <a href="/#/register">Register</a> before you can comment.</h3>
</div>
<form ng-submit="addComment()" ng-show="isLoggedIn()" style="margin-top:30px;">
<h3>Add a new comment</h3>
<div class="form-group">
<input type="text" class="form-control" placeholder="Comment" ng-model="body"></input>
</div>
<button type="submit" class="btn btn-primary">Post</button>
</form>
</script>
<script type="text/ng-template" id="/register.html">
<div class="page-header">
<h1>Flapper News</h1>
</div>
<div ng-show="error" class="alert alert-danger row">
<span>{{ error.message }}</span>
</div>
<form ng-submit="register()"
style="margin-top:30px;">
<h3>Register</h3>
<div class="form-group">
<input type="text"
class="form-control"
placeholder="Username"
ng-model="user.username"></input>
</div>
<div class="form-group">
<input type="password"
class="form-control"
placeholder="Password"
ng-model="user.password"></input>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
</script>
<script type="text/ng-template" id="/login.html">
<div class="page-header">
<h1>Flapper News</h1>
</div>
<div ng-show="error" class="alert alert-danger row">
<span>{{ error.message }}</span>
</div>
<form ng-submit="logIn()"
style="margin-top:30px;">
<h3>Log In</h3>
<div class="form-group">
<input type="text"
class="form-control"
placeholder="Username"
ng-model="user.username"></input>
</div>
<div class="form-group">
<input type="password"
class="form-control"
placeholder="Password"
ng-model="user.password"></input>
</div>
<button type="submit" class="btn btn-primary">Log In</button>
</form>
</script>
</body>
</html>
本教程指示不在MainCtrl
中的posts.create函数中包含post.author,也不更新mongoose模型。在此设置下,{{post.author}}
也不会显示。
非常感谢任何帮助。
编辑:这也不是浏览器缓存错误。
答案 0 :(得分:0)
如果post.author是唯一没有显示的字段,那么我认为问题是你没有正确地将作者字段存储在mongoDB的Post模型中,你可能存储了一个未定义的值。
这可能是因为@Inject
可能正在评估未定义,因为你的jwt没有被正确解码而不是
@Dependent
尝试
req.payload.username
您的router.post('/posts', auth, function(req, res, next) {
var post = new Post(req.body);
post.author = req.payload.username;
post.save(function(err, post){
已经附加了router.post('/posts', auth, function(req, res, next) {
var post = new Post(req.body);
post.save(function(err, post){
属性
req.body
工厂中username
。重新分配是没有意义的。
我也完成了教程并让作者属性正常工作,如果您觉得有意,可以查看挡板文件夹中的github。