Angular 5 + MongoDB 3.0.1注册数据提交及数据库插入问题咨询
问题1:onSubmitRegistration方法是否正确发送了数据?
答案是没有,核心问题出在三个地方:
- 前端模板的
ngModel绑定错误:你用了单向绑定(ngModel),这只能把组件的值同步到视图,却没法把用户输入的内容同步回组件的user对象,必须用双向绑定[(ngModel)]。 - 组件内的
user对象未初始化:你只声明了user的类型,但没创建实例,导致用户输入时没有可绑定的对象,数据根本存不进去。 - 后端未配置请求体解析中间件:Express默认不会自动解析JSON格式的请求体,就算前端发了数据,后端的
req.body也会是空对象,后续插入数据库自然失败。
问题2:如何修改代码实现用户数据正确存入MongoDB?
下面分前端、后端给出具体修复方案:
前端修改
- 修复模板的双向绑定
把registration.component.html里的(ngModel)替换成双向绑定语法:
<form class="example-form" (ngSubmit)="onSubmitRegistration(user)"> <mat-input-container class="full-width-input"> User * <input matInput name="user-userName" [(ngModel)]="user.userName" required> </mat-input-container> <mat-input-container class="full-width-input"> Password * <input matInput name="user-password" type="password" [(ngModel)]="user.password" required> </mat-input-container> <mat-card-footer> <button mat-raised-button color="primary" type="submit">Zapisz</button> </mat-card-footer> <br /> </form>
- 初始化
user对象并完善错误处理
在registration.component.ts里初始化user,同时增加日志和错误捕获,方便排查问题:
import {AuthService} from './../auth/auth.service'; import {Component, OnInit, Input} from '@angular/core'; import {FormGroup, FormBuilder, Validators} from '@angular/forms'; import {User} from '../auth/user'; @Component({ selector: 'app-registration', templateUrl: './registration.component.html', styleUrls: ['../login/login.component.css'] }) export class RegistrationComponent implements OnInit { private formSubmitAttempt: boolean; errorMessage: string; // 去掉@Input,组件自己管理user对象,不需要父组件传入 user: User = { userName: '', password: '' }; @Input() createHandler: Function; constructor(private fb: FormBuilder, private authService: AuthService) {} ngOnInit() {} onSubmitRegistration(user: User) { // 先打印确认要发送的数据 console.log('准备提交的用户数据:', user); this.authService.registration(user) .then((newUser: User) => { this.createHandler(newUser); console.log('注册成功返回数据:', JSON.stringify(newUser)); }) .catch(err => { console.error('注册请求失败:', err); this.errorMessage = '注册失败,请稍后重试'; }); } }
- 完善AuthService的请求配置
在auth.service.ts里指定请求头为JSON格式,并增加错误处理:
import {Injectable} from '@angular/core'; import {Router} from '@angular/router'; import {BehaviorSubject} from 'rxjs/BehaviorSubject'; import {User} from './user'; import {Http, Headers, RequestOptions, Response} from '@angular/http'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/toPromise'; @Injectable() export class AuthService { private loggedIn = new BehaviorSubject<boolean>(false); result: any; get isLoggedIn() { return this.loggedIn.asObservable(); } constructor(private router: Router, private _http: Http) {} registration(newUser: User): Promise<void | User> { const headers = new Headers({ 'Content-Type': 'application/json' }); const options = new RequestOptions({ headers: headers }); return this._http.post('/api/users', JSON.stringify(newUser), options) .toPromise() .then(response => { console.log('后端响应:', response); return response.json().data as User; }) .catch(err => { console.error('请求错误详情:', err); throw err; // 把错误抛给组件处理 }); } getUsers() { return this._http.get('/api/users').map(result => this.result = result.json().data); } }
后端修改
- 安装并配置body-parser中间件
首先安装依赖:
npm install body-parser --save
然后在你的Express入口文件(比如server.js/app.js)里引入并启用:
const express = require('express'); const bodyParser = require('body-parser'); const app = express(); // 解析JSON格式请求体 app.use(bodyParser.json()); // 解析URL编码格式请求体 app.use(bodyParser.urlencoded({ extended: true })); // 引入你的路由 const apiRoutes = require('./server/routes/api'); app.use('/api', apiRoutes);
- 修复POST路由参数并完善插入逻辑
server/routes/api.js里的POST路由参数写错了(把res写成了client),同时完善数据库插入的错误处理和响应:
const express = require('express'); const router = express.Router(); const MongoClient = require('mongodb').MongoClient; const ObjectID = require('mongodb').ObjectID; // Connect 27017 const connection = (closure) => { return MongoClient.connect('mongodb://localhost:27017/mean', (err, client) => { if (err) return console.log(err); let db = client.db('mean'); closure(db); }); }; // Error handling const sendError = (err, res) => { // 改用局部响应对象,避免污染全局状态 const errorResponse = { status: 501, data: [], message: typeof err == 'object' ? err.message : err }; res.status(501).json(errorResponse); }; // Response handling let response = { status: 200, data: [], message: null }; // Get users router.get('/users', (req, res) => { connection((db) => { db.collection('users') .find() .toArray() .then((users) => { response.data = users; res.json(response); }) .catch((err) => { sendError(err, res); }); }); }); // 修复路由参数,完善插入逻辑 router.post("/users", (req, res) =>{ console.log('收到的请求体:', req.body); // 打印确认是否拿到数据 const myobj = { name: req.body.userName, password: req.body.password }; connection((db) => { db.collection('users').insertOne(myobj, (err, doc) =>{ if (err) { console.error('插入数据库失败:', err); return sendError(err, res); } console.log('成功插入用户:', doc.ops[0]); response.data = doc.ops[0]; res.json(response); }); }); }); module.exports = router;
做完以上修改后,前端就能正确传递用户输入的数据,后端也能解析并插入到MongoDB中。你可以通过控制台打印的日志,确认数据传输和数据库插入的状态。
内容的提问来源于stack exchange,提问作者user2129896
相关产品推荐
相关产品推荐

