Req.Body 是 Angular 2 表单提交 + Bodyparser 上的空对象
Posted
技术标签:
【中文标题】Req.Body 是 Angular 2 表单提交 + Bodyparser 上的空对象【英文标题】:Req.Body is empty object on Angular 2 Form submission + Bodyparser 【发布时间】:2017-05-18 23:03:52 【问题描述】:我的应用程序中有一个反应式(模型驱动)表单,我无法将表单数据传递给 mongoose。当我通过 http post 方法提交数据时,我不断收到错误,因为后端正在接收一个空对象。
我知道后端可以正常工作,因为当我使用 Postman 提交帖子请求时,我得到的结果状态为“201 Created”。过去几年我一直在阅读论坛和各种博客几天,我仍然很难过。
问题
-
我需要更改哪些表单数据才能到达后端
适当吗?
Angular2 表单数据提交是否有最佳实践?
注意事项 看起来可能缺少一些内容,例如 URL,并且您会注意到表单中的一些附加字段。为了简洁起见,我故意不包括所有这些,并混淆了到我的后端的实际链接。
后端 - 猫鼬
jobs.controllers.js
var mongoose = require('mongoose');
var Job = mongoose.model('Job');
module.exports.addNewJob = function(req, res)
console.log(req.body);//added to see req payload from client
Job
.create(
_id: req.body.jobid,
desc: req.body.name,
type: req.body.jobType,
location: req.body.location
,function(err, job)
if(err)
console.log("Error creating job");
res
.status(400)
.json(err);
else
console.log("Job Created", job);
res
.status(201)
.json(job);
);
jobs.model.js
var mongoose = require('mongoose');
var jobSchema = new mongoose.Schema(
_id:
type: String
,
desc:
type: String
,
type:
type: String,
default: "TM"
,
location: String
);
mongoose.model('Job', jobSchema);
db.js
var mongoose = require ('mongoose');
var dburl = 'mongodb://localhost:27017/dbname';
mongoose.connect(dburl);
mongoose.connection.on('connected', function()
console.log('Mongoose connected to ' + dburl);
);
mongoose.connection.on('disconnected', function()
console.log('Mongoose disconnedted');
);
mongoose.connection.on('error', function(err)
console.log('Mongoose connection error: ' + err);
);
require('./jobs.model.js');
index.js
var express = require('express');
var router = express.Router();
var ctrlJobs = require('../controllers/jobs.controllers.js');
router
.route('/jobs')
.get(ctrlJobs.jobsGetAll)
.post(ctrlJobs.addNewJob);
module.exports = router;
app.js
require('./api/data/db.js');
var express = require('express');
var app = express ();
var path = require('path');
var bodyParser = require('body-parser');
var routes = require('./api/routes');
app.use(function(req, res, next)
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
);
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.urlencoded(extended: false));
app.use('/api', routes);//Goes to index.js
前端 - Angular2 最终
jobs.service
import Injectable from '@angular/core';
import Http, Response, Headers, RequestOptions from '@angular/http';
import Observable from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
@Injectable()
export class JobsService
private _url = "http://123.456.789.100/api/jobs"; //removed actual address for post
constructor(private _http: Http)
addNewJob(form: Object)
let headers = new Headers('Content-Type':'application/json');
let options = new RequestOptions(headers: headers);
return this._http
.post(this._url, JSON.stringify(form), options)
.map(this.extractData)
.catch(this.handleError);
private extractData(res: Response)
let body = res.json();
return body.data || ;
private handleError (error: Response | any)
let errMsg: string;
if (error instanceof Response)
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `$error.status - $error.statusText || '' $err`;
else
errMsg = error.message ? error.message : error.toString();
console.error(errMsg);
return Observable.throw(errMsg);
job-form.component
import Component, OnInit from '@angular/core';
import FormBuilder, FormGroup, Validators from '@angular/forms';
import Router, ActivatedRoute from '@angular/router';
import JobsService from './jobs.service';
@Component(
templateUrl: './job-form.component.html',
providers: [JobsService]
)
export class JobFormComponent implements OnInit
id: string;
job: any;
jobForm: FormGroup;
title: string;
constructor(
private _fb: FormBuilder,
private _router: Router,
private _route: ActivatedRoute,
private _jobsService: JobsService
)
ngOnInit(): void
this.jobForm = this._fb.group(
jobid: ['', Validators.required],
name: ['', Validators.required],
jobType: ['', Validators.required],
location: ['', Validators.required]
);
this.id = this._route.snapshot.params['id'];
this.title = this.id ? "Edit Job" : "Create New Job";
save(form: any)
console.log(this.jobForm.value);
this._jobsService.addNewJob(form).subscribe((dataResponse) =>
console.log("Submitting" + dataResponse);
);
reset()
this.jobForm.reset();
job-form.component.html
<form [formGroup]="jobForm" novalidate (ngSubmit)="save(jobForm.value)">
<div class="row">
<div class="col-xs-2">
<label>Job Number</label>
<input [ngModel]="job?.jobid ? job.jobid : ''" class="form-control" type="text" formControlName="jobid">
</div>
<div class="col-xs-8">
<label>Title</label>
<input [ngModel]="job?.name ? job.name : ''" class="form-control" type="text" formControlName="name">
</div>
<div class="col-xs-2">
<label>Type</label><br />
<select [ngModel]="job?.jobType ? job.jobType : ''"class="form-control" formControlName="jobType">
<option value="TM">T&M</option>
<option value="LS">Lump Sum</option>
</select>
</div>
</div>
<div class="row">
<div class="col-xs-2">
<label>Status</label><br />
<select class="form-control" formControlName="status" [ngModel]="job?.status ? job.status : ''">
<option value="Pending">Pending</option>
<option value="Active">Active</option>
<option value="On Hold">On Hold</option>
<option value="Complete">Complete</option>
<option value="Closed">Closed</option>
</select>
</div>
<div class="col-xs-5">
<label>Location</label>
<input [ngModel]="job?.location ? job.location : ''" class="form-control" type="text" formControlName="location">
</div>
</div>
<br />
<div class="row">
<div class="col-xs-1">
<button type="btn btn-primary" class="btn btn-primary" [disabled]="!jobForm.valid">Submit</button>
</div>
<div class="col-xs-1">
<button class="btn btn-default" (click)="reset()">Reset</button>
</div>
</div>
</form>
测试
将 headers 设置为 application/json,req.body 是一个空对象
当我将标题设置为 application/x-www-form-urlencoded 时,req.body 显示
'"jobid":"8746541","name":"asdfasdfasdfasdf","jobType":"LS","location":"asdfa"':''
提交时 XHR
邮递员Success
【问题讨论】:
【参考方案1】:在文件 jobs.service 中,您将 Header 设置为
'Content-Type':'application/json'
在 index.js 文件中,您正在处理正文请求
app.use(bodyParser.urlencoded(extended: false));
所以你可以做两种解决方案。
1.) 在 jobs.service 中进行更改
'Content-Type': 'application/x-www-form-urlencoded'
2.) 或更改 index.js
app.use(bodyParser.json());
【讨论】:
【参考方案2】:解决方案
将行 app.use(bodyParser.json());
添加到 app.js。本质上,这告诉应用程序它应该原生地理解 JSON。现在在应用程序中提交表单会导致将新记录添加到 mongodb。
【讨论】:
【参考方案3】:在 app.js 中添加以下中间件...
app.use(bodyParser.json());
app.use(bodyParser.urlencoded(extended: true));
欲了解更多信息,请访问此网站:link!
【讨论】:
【参考方案4】:1.在前端级别:- 使用反应驱动形式时 通过前端类文件绑定 对象作为 getRawValue()。
1.1 前端到后端的集成 例如我们确定的服务 调用方法时我们必须通过 保存时绑定的对象包括 headers 就像它是 post 方法一样。
通过要求 bodyparser 添加中间件。将 use 用作 bodyparser.json。
在邮递员中导航到特定路线,首先检查新数据并发布。
现在绑定前端对象。
我们传递给 post rest API 方法的是来自前端的对象。
快乐的结局?
【讨论】:
以上是关于Req.Body 是 Angular 2 表单提交 + Bodyparser 上的空对象的主要内容,如果未能解决你的问题,请参考以下文章
req.body 未定义并使用 Angular 进行快速 API 测试
使用 http 时,req.body 为空 。在 angular 和 node.js 中发布