MEAN 应用程序中项目的单独页面
Posted
技术标签:
【中文标题】MEAN 应用程序中项目的单独页面【英文标题】:Separate pages for items in MEAN application 【发布时间】:2014-09-08 10:20:21 【问题描述】:我正在使用 Node、Express、Mongoose 和 Angular 编写应用程序。我可以在一个页面上显示所有项目。我的下一步是为数据库中的项目编写单独的页面,因此我创建了路线:
app.get '/products/:product_id', (req, res) ->
Product.findById req.params.product_id, (err, product) ->
res.send(err) if (err)
res.render('product.html', name: product.name )
return
return
一切都很酷,我可以在 product.html 中使用 显示名称,但 Angular 不起作用。没有 '/:product_id' 工作。 这是我获得所有产品的途径:
app.get '/api/products', (req, res) ->
Product.find (err, products) ->
if (err)
res.send(err)
res.json(products); # return all products in JSON format
return
return
在正面:
$http.get('/api/products')
.success (data) ->
$scope.products = data
console.log(data)
return
.error (data) ->
console.log('Error: ' + data)
return
那么,我如何编写应用程序,在其中我转到http://mydomain.com/products/53c68728c7e5a5381a000002 然后会显示一项? (53c68728c7e5a5381a000002 是 id)
【问题讨论】:
我对 MEAN 的处理方式相当陌生,但从逻辑上思考,如果 Angular 在您的路由上执行 HTTP GET 并且它在技术上返回渲染 html,那不会搞砸?例如:您正在使用数据呈现页面。使用 Angular,您在页面被渲染到返回 html 的同一路由后向路由发出请求。您可能应该设置您的 products/:product_id 类似于您的 api/products,然后当您渲染角度时,让它请求 api/products/:product_id。 但是如何发送到 angular id?当我输入 www.domain.com/products/643284 时,angular 怎么知道,id 是 643284? 【参考方案1】:如果我理解正确,您不会在角度侧发送 id。
在这种情况下,您应该创建一个 $resource 服务:
myApp.factory('ProductService', [ '$resource', function($resource)
return $resource('http://mydomain.com/products/:id',
id : '@_id'
);
]);
然后在你的控制器中调用它:
myApp.controller('MyCtrl', ['$scope', 'ProductService', '$routeParams',
function($scope, ProductService, $routeParams)
$scope.findOne = function()
$scope.product = ProductService.get(
id : $routeParams.id
);
;
]);
仅当您在控制器声明中包含您的服务(以及 routeParams 如果它还没有)并且您在前端正确设置了您的路由时,它才会起作用:
myApp.config(['$routeProvider', function($routeProvider)
$routeProvider.when('/product/:id', templateUrl: 'partials/product.html', controller: 'MyCtrl');
]);
【讨论】:
我认为唯一的问题是一旦向 /products/:product_id 发出请求,它将返回 html。我要么更改服务器 products/:product_id 请求以返回 JSON 数据,要么将客户端资源 url 更改为 /api/products/:id。除此之外,这就是我的想法。 你说得对,我绝对建议只将 JSON 数据发送到 AngularJS。 也许我很笨,但是不能在我的控制器中调用 $resource 服务,这个:app.controller 'StoreController', ['$scope', 'ProductService', '$routeParams', ($scope, ProductService, $routeParams) -> 这个 app.controller 'StoreController', ($scope, ProductService, $http) -> 对我不起作用。最后一件事,myApp.config,也必须在控制器(前端)的文件中? 您应该查看 angular seed 项目github.com/angular/angular-seed 以更好地了解我正在使用的结构。您还可以使用 MEAN 堆栈的样板应用程序(请参阅 mean.js 或 mean.io),它们为您提供了基本的 CRUD,这就是您似乎正在做的事情。 添加angular-route.min.js很重要。我在 1.2.0 版和 1.1.5 版中使用了 angular-route 是不是很糟糕?【参考方案2】:还是不行。 路线(后端):
app.get '/products/:product_id', (req, res) ->
Product.findById req.params.product_id, (err, product) ->
res.send(err) if (err)
res.render('product.html', name: product.name )
return
return
App.js(正面):
config(['$routeProvider', ($routeProvider) ->
$routeProvider.when('/products/:id', templateUrl: 'views/product.html', controller: 'StoreControllerOne');
Controllers.js(前):
.controller 'StoreControllerOne', ['$scope', '$http', 'ProductService', '$routeParams',
($scope, $http, ProductService, $routeParams) ->
$scope.findOne = ->
$scope.product = ProductService.get(
id : $routeParams.id
);
console.log($scope.product.id)
return
]
Services.js(前面):
.factory('ProductService', [ '$resource', ($resource) ->
return $resource('/products/:id',
id : '@_id'
);
]);
当我去 www.mydomain.com/products/53c92d5dda9cef6c23000002 时,JS 控制台说,例如找不到 www.mydomain.com/products/javascripts/app.js,但是这个文件在 www.mydomain .com/javascripts/app.js。因为在 html 文件中添加 ../ 不是好的做法,并且它不适用于指令。
【讨论】:
你解决过这个问题吗? 您是在使用自己的 MEAN 堆栈还是其中一个已经存在的库? 我从 scotch.io/tutorials/javascript/… 和 codeschool (AngularJS) 开始了本教程。我正在开发这个项目。【参考方案3】:我不得不做一些研究以确保我没有错,因为我对 MEAN 没有很多经验。然而,看看 meanjs 及其实现,它似乎保持不变。
根据示例文章 routes.js https://github.com/meanjs/mean/blob/master/app/routes/articles.server.routes.js
app.route('/articles/:articleId')
.get(articles.read) //<----THIS GUY RIGHT HERE
.put(users.requiresLogin, articles.hasAuthorization, articles.update)
.delete(users.requiresLogin, articles.hasAuthorization, articles.delete);
他们调用articles.read。所以我们在控制器部分找到了这个函数。 https://github.com/meanjs/mean/blob/master/app/controllers/articles.server.controller.js
这个函数抓取并返回req.article
exports.read = function(req, res)
res.jsonp(req.article);
;
如果您深入挖掘,使用 mongoose 会发现并添加到 req 中。
exports.articleByID = function(req, res, next, id)
Article.findById(id).populate('user', 'displayName').exec(function(err, article)
if (err) return next(err);
if (!article) return next(new Error('Failed to load article ' + id));
req.article = article;
next();
);
;
在文章中的角度控制器 https://github.com/meanjs/mean/blob/master/public/dist/application.js
$scope.findOne = function ()
$scope.article = Articles.get( articleId: $stateParams.articleId );
;
您仍在返回 HTML 作为请求的一部分。让 Angular 处理路由并将数据从请求中提取到您的节点服务器。
app.get '/products/:product_id', (req, res) ->
Product.findById req.params.product_id, (err, product) ->
res.send(err) if (err)
res.json( name: product.name )
return
return
或者类似的东西。当您的资源甚至是一个简单的 http 请求被发送到 /products/:product_id
时,您通过 res 返回的任何内容都是它试图解析的内容。如果您正在执行 res.render ,它将作为响应返回并中断,因为您期待其他内容。
编辑参考您正在使用的教程的评论*
添加到服务器端 - 这将添加一个 api 路由以返回该 product/product_id 的 JSON 数据
//View a product
app.get('/api/products/:product_id', function(req, res)
Product.findOne(
_id : req.params.product_id
, function(err, product)
if (err)
res.send(err);
res.json(product);
);
);
添加到前端 Angular 控制器 - 无论您在为产品执行 http.get 的任何位置都执行此操作
//id is a placeholder for however you are passing in the product id
$http.get('/api/products/' + id)
.success(function(data)
$scope.product = data;
console.log(data);
)
.error(function(data)
console.log('Error: ' + data);
);
【讨论】:
角路线不起作用。当我转到mydomain.com/products/53c92d5dda9cef6c23000002 时,它会在每个 javascript 文件中打开 index.html,并显示“Uncaught SyntaxError: Unexpected token github.com/dakolech/angular-GemStore我做错了什么? 是的,看起来所有未公开解析的请求都获取了 index.html 文件,这是由于路由不起作用。不过,我会就此提出一个新问题。以上是关于MEAN 应用程序中项目的单独页面的主要内容,如果未能解决你的问题,请参考以下文章
MEAN Stack:Cast to ObjectId 值“:id”失败
nginx 中 MEAN-stack 应用程序的漂亮 url