在MEANJS的CRUD的URL中使用slug

我需要在URL中使用slug而不是文章ID,所以我改变了由meanjs给出的文章示例中的一些东西,但是我有一个问题,我可以列出,查看和编辑,但是我不能创build新的。 我不熟悉MEAN栈,所以很可能我的修改中有一些非常错误的地方,但是我可以想办法让它工作。

创build文章时,标题会从标题中生成。 我也想被编辑,但如果我把编辑的slug字段也编辑function也停止工作…

代码来自使用垂直模块的meanjs的0.4分支。

在articles.client.service.js中,如果我改变了:

angular.module('articles').factory('Articles', ['$resource', function($resource) { return $resource('api/articles/:articleSlug', { articleSlug: '@slug' }, { update: { method: 'PUT' } }); } ]); 

对于:

 angular.module('articles').factory('Articles', ['$resource', function($resource) { return $resource('api/articles/:articleSlug', { articleSlug: '@_id' }, { update: { method: 'PUT' } }); } ]); 

创buildfunction开始工作,但编辑function停止… -.-

任何帮助将不胜感激。 谢谢

这是我的articles.server.routes.js

 'use strict'; /** * Module dependencies. */ var articlesPolicy = require('../policies/articles.server.policy'), articles = require('../controllers/articles.server.controller'); module.exports = function(app) { // Articles collection routes app.route('/api/articles').all(articlesPolicy.isAllowed) .get(articles.list) .post(articles.create); // Single article routes app.route('/api/articles/:articleSlug').all(articlesPolicy.isAllowed) .get(articles.read) .put(articles.update) .delete(articles.delete); // Finish by binding the article middleware app.param('articleSlug', articles.articleBySlug); }; 

这是我的articles.client.service.js

 'use strict'; //Articles service used for communicating with the articles REST endpoints angular.module('articles').factory('Articles', ['$resource', function($resource) { return $resource('api/articles/:articleSlug', { articleSlug: '@slug' }, { update: { method: 'PUT' } }); } ]); 

这是我的articles.client.controller.js

 'use strict'; angular.module('articles').controller('ArticlesController', ['$scope', '$stateParams', '$location', 'Authentication', 'Articles', function($scope, $stateParams, $location, Authentication, Articles) { $scope.authentication = Authentication; $scope.create = function() { var article = new Articles({ slug: this.title.toLowerCase().replace(/ /g, '-'), title: this.title, content: this.content }); article.$save(function(response) { $location.path('articles/' + response.slug); $scope.slug = ''; $scope.title = ''; $scope.content = ''; }, function(errorResponse) { $scope.error = errorResponse.data.message; }); }; $scope.remove = function(article) { if (article) { article.$remove(); for (var i in $scope.articles) { if ($scope.articles[i] === article) { $scope.articles.splice(i, 1); } } } else { $scope.article.$remove(function() { $location.path('articles'); }); } }; $scope.update = function() { var article = $scope.article; article.$update(function() { $location.path('articles/' + article.slug); }, function(errorResponse) { $scope.error = errorResponse.data.message; }); }; $scope.find = function() { $scope.articles = Articles.query(); }; $scope.findOne = function() { $scope.article = Articles.get({ articleSlug: $stateParams.articleSlug }); }; } ]); 

这是我的articles.server.controller.js

 'use strict'; /** * Module dependencies. */ var _ = require('lodash'), path = require('path'), mongoose = require('mongoose'), Article = mongoose.model('Article'), errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller')); /** * Create a article */ exports.create = function(req, res) { var article = new Article(req.body); article.user = req.user; article.save(function(err) { if (err) { return res.status(400).send({ message: errorHandler.getErrorMessage(err) }); } else { res.json(article); } }); }; /** * Show the current article */ exports.read = function(req, res) { res.json(req.article); }; /** * Update a article */ exports.update = function(req, res) { var article = req.article; article.title = req.body.title; article.content = req.body.content; article.save(function(err) { if (err) { return res.status(400).send({ message: errorHandler.getErrorMessage(err) }); } else { res.json(article); } }); }; /** * Delete an article */ exports.delete = function(req, res) { var article = req.article; article.remove(function(err) { if (err) { return res.status(400).send({ message: errorHandler.getErrorMessage(err) }); } else { res.json(article); } }); }; /** * List of Articles */ exports.list = function(req, res) { Article.find().sort('-created').populate('user', 'displayName').exec(function(err, articles) { if (err) { return res.status(400).send({ message: errorHandler.getErrorMessage(err) }); } else { res.json(articles); } }); }; /** * Article middleware */ exports.articleBySlug = function(req, res, next, slug) { Article.findOne({'slug': slug}).populate('user', 'displayName').exec(function(err, article) { if (err) return next(err); if (!article) return next(new Error('Failed to load article ' + slug)); req.article = article; next(); }); }; 

我克隆了0.4.0分支,这就是我所做的,通过在所有情况下应该使用slug来进行路由select。

1-将slug添加到文章模式并确保其独特的article.server.model.js

 slug: { type: String, default: '', trim: true, unique: true, required: 'Slug cannot be blank' } 

2-重新将物品控制器中的更新方法包括在内:

  exports.update = function(req, res) { var article = req.article; article = _.extend(article , req.body); article.save(function(err) { if (err) { return res.status(400).send({ message: errorHandler.getErrorMessage(err) }); } else { res.json(article); } }); }; 

3-向文章控制器添加一个方法来通过slug(或实际上req.query中的任何内容)来查找文章

 exports.readBySlug = function(req , res){ Article.findOne(req.query).populate('user', 'displayName').exec(function(err, article) { if (err) { return res.status(400).send({ message: errorHandler.getErrorMessage(err) }); } else { res.json(article); } }); }; 

3-然后添加一个路由指向该方法(确保在路由configuration的开始处添加路由,或者至less在更新之前添加路由,删除路由)

 app.route('/api/articles/read-slug').get(articlesPolicy.isAllowed , articles.readBySlug); 

4-修改策略以允许GET到该路由,文章策略:

 exports.invokeRolesPolicies = function() { acl.allow([{ roles: ['admin'], allows: [{ resources: '/api/articles', permissions: '*' }, { resources: '/api/articles/:articleId', permissions: '*' }] }, { roles: ['user'], allows: [{ resources: '/api/articles', permissions: ['get', 'post'] }, { resources: '/api/articles/:articleId', permissions: ['get'] }] }, { roles: ['guest'], allows: [{ resources: '/api/articles', permissions: ['get'] }, { resources: '/api/articles/:articleId', permissions: ['get'] }] }, { roles: ['admin','user','guest'], allows: [{ resources: '/api/articles/read-slug', permissions: ['get'] }] }]); }; 

在前端:

1-更改物品路线中的路线,以使用slu instead代替id:

  state('articles.view', { url: '/:articleSlug', templateUrl: 'modules/articles/views/view-article.client.view.html' }). state('articles.edit', { url: '/:articleSlug/edit', templateUrl: 'modules/articles/views/edit-article.client.view.html' }); 

2-在视图中更改链接以反映路线变化article.view({articleSlug: article.slug} ,与article.edit相同

3-向文章服务中添加一个方法来获取slug文章:

  return $resource('api/articles/:articleId/:controller', { articleId: '@_id' }, { update: { method: 'PUT' } , getBySlug: { method: 'GET', params: { controller: 'read-slug' } } }); 

4-对文章控制器中的findOne方法进行重新分解,以使用我们刚刚定义的方法(在文章控制器中):

  $scope.findOne = function() { $scope.article = Articles.getBySlug({ slug: $stateParams.articleSlug }); 

5 – 最后重新更新并创build包含slug(在文章控制器中):

  $scope.update = function() { var article = $scope.article; article.slug = article.title.toLowerCase().replace(/ /g, '-'); console.log(article); article.$update(function() { $location.path('articles/' + article.slug); }, function(errorResponse) { $scope.error = errorResponse.data.message; }); }; $scope.create = function() { var article = new Articles({ slug: this.title.toLowerCase().replace(/ /g, '-'), title: this.title, content: this.content }); article.$save(function(response) { $location.path('articles/' + response.slug); $scope.title = ''; $scope.content = ''; }, function(errorResponse) { $scope.error = errorResponse.data.message; }); };