当我尝试 update 用户时,出现服务器错误,我的应用程序崩溃,我必须重新开始。这是我在浏览器端看到的错误:
这是我的 TS 文件:
import { Location } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { User, UsersService } from '@eshop-repository/users';
import { MessageService } from 'primeng/api';
import { timer } from 'rxjs';
@Component({
selector: 'admin-users-form',
templateUrl: './users-form.component.html',
})
export class UsersFormComponent implements OnInit {
form!: FormGroup;
isSubmitted = false;
editmode = false;
currentUserId!: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
countries: any;
constructor(
private messageService: MessageService,
private formBuilder: FormBuilder,
private usersService: UsersService,
private location: Location,
private route: ActivatedRoute,
) {}
ngOnInit(): void {
this._initUserForm();
this._getCountries();
this._checkEditMode();
}
private _initUserForm() {
this.form = this.formBuilder.group({
name: ['', Validators.required],
password: ['', Validators.required],
//email: ['', [Validators.required, Validators.email]],
email: ['', Validators.required],
phone: ['', Validators.required],
isAdmin: [false],
street: [''],
apartment: [''],
zip: [''],
city: [''],
country: ['']
});
}
private _getCountries() {
this.countries = this.usersService.getCountries();
}
private _addUser(user: User) {
this.usersService.createUser(user).subscribe(
(user: User) => {
this.messageService.add({
severity: 'success',
summary: 'Success',
detail: `User ${user.name} is created!`
});
timer(2000)
.toPromise()
.then(() => {
this.location.back();
});
},
() => {
this.messageService.add({
severity: 'error',
summary: 'Error',
detail: 'User is not created!'
});
}
);
}
private _updateUser(user: User) {
this.usersService.updateUser(user).subscribe(
() => {
this.messageService.add({
severity: 'success',
summary: 'Success',
detail: 'User is updated!'
});
timer(2000)
.toPromise()
.then(() => {
this.location.back();
});
},
() => {
this.messageService.add({
severity: 'error',
summary: 'Error',
detail: 'User is not updated!'
});
}
);
}
private _checkEditMode() {
this.route.params.subscribe((params) => {
if (params['id']) {
this.editmode = true;
this.currentUserId = params['id'];
this.usersService.getUser(params['id']).subscribe((user) => {
this.form.controls['name'].setValue(user.name);
this.form.controls['email'].setValue(user.email);
this.form.controls['phone'].setValue(user.phone);
this.form.controls['isAdmin'].setValue(user.isAdmin);
this.form.controls['street'].setValue(user.street);
this.form.controls['apartment'].setValue(user.apartment);
this.form.controls['zip'].setValue(user.zip);
this.form.controls['city'].setValue(user.city);
this.form.controls['country'].setValue(user.country);
this.form.controls['password'].setValidators([]);
this.form.controls['password'].updateValueAndValidity();
});
}
});
}
onSubmit() {
this.isSubmitted = true;
if (this.form.invalid) {
return;
}
const user: User = {
id: this.currentUserId,
name: this.form.controls['name'].value,
email: this.form.controls['email'].value,
password: this.form.controls['password'].value,
phone: this.form.controls['phone'].value,
isAdmin: this.form.controls['isAdmin'].value,
street: this.form.controls['street'].value,
apartment: this.form.controls['apartment'].value,
zip: this.form.controls['zip'].value,
city: this.form.controls['city'].value,
country: this.form.controls['country'].value
};
if (this.editmode) {
this._updateUser(user);
} else {
this._addUser(user);
}
}
onCancle() {
this.location.back();
}
get userForm() {
return this.form.controls;
}
}
这是我的 HTML 文件:
<p-toast></p-toast>
<div class="admin-page">
<p-card [header]="editmode ? 'Edit User' : 'Add User'" subheader="You can add or edit users here">
<div class="p-grid p-mb-5">
<div class="p-col-12">
<p-toolbar>
<div class="p-toolbar-group-left"></div>
<div class="p-toolbar-group-right">
<p-button
styleClass="p-button-primary p-mr-2"
[label]="editmode ? 'Update' : 'Create'"
icon="pi pi-plus"
(click)="onSubmit()"
></p-button>
<p-button
styleClass="p-button-secondary"
label="Cancle"
icon="pi pi-arrow-circle-left"
(click)="onCancle()"
></p-button>
</div>
</p-toolbar>
</div>
</div>
<div class="grid">
<div class="col-12">
<form [formGroup]="form">
<div class="card">
<div class="formgrid grid">
<div class="field col-4">
<label for="name">Name</label>
<input formControlName="name" id="name" type="text" pInputText />
<small *ngIf="this.form.controls['name'].invalid && isSubmitted" class="p-error"
>Name is required</small
>
</div>
<div class="field col-4">
<label for="email">Email</label>
<input formControlName="email" id="email" type="text" pInputText />
<small *ngIf="this.form.controls['email'].invalid && isSubmitted" class="p-error"
>
<span>*ngIf="this.form.controls['email'].errors['required']">email is required</span>
>
</small>
</div>
<div class="field col-4">
<label for="password">Password</label>
<input formControlName="password" id="password" type="password" pInputText />
<small *ngIf="this.form.controls['password'].invalid && isSubmitted" class="p-error"
>Password is required</small
>
</div>
<div class="field col-4">
<label for="phone">Phone</label><br />
<p-inputMask
mask="(999) 999-9999"
formControlName="phone"
placeholder="(999) 999-9999"
></p-inputMask>
<small *ngIf="this.form.controls['phone'].invalid && isSubmitted" class="p-error"
>phone is required</small
>
</div>
<div class="field col-4">
<label for="isAdmin">Is Admin</label><br />
<p-inputSwitch formControlName="isAdmin"></p-inputSwitch>
</div>
</div>
<div class="fluid formgrid grid">
<div class="field col-4">
<label for="street">Street</label>
<input formControlName="street" id="street" type="text" pInputText />
</div>
<div class="field col-4">
<label for="street">Apartment</label>
<input formControlName="apartment" id="apartment" type="text" pInputText />
</div>
<div class="field col-4">
<label for="street">Zip Code</label>
<input formControlName="zip" id="zip" type="text" pInputText />
</div>
<div class="field col-4">
<label for="city">City</label>
<input formControlName="city" id="city" type="text" pInputText />
</div>
<div class="field col-4">
<label for="country">Country</label><br />
<p-dropdown
[options]="countries"
formControlName="country"
optionLabel="name"
optionValue="id"
[filter]="true"
filterBy="name"
[showClear]="true"
placeholder="Select a Country"
></p-dropdown>
</div>
</div>
</div>
</form>
</div>
</div>
</p-card>
</div>
最后这是我的用户服务 TS 文件(调用路由 API 的地方):
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { User } from '../models/user';
import { environment } from 'environments/environment';
import * as countriesLib from 'i18n-iso-countries';
declare const require: (arg0: string) => countriesLib.LocaleData;
@Injectable({
providedIn: 'root'
})
export class UsersService {
apiURLUsers = environment.apiUrl + 'users';
constructor(private http: HttpClient) {
countriesLib.registerLocale(require('i18n-iso-countries/langs/en.json'));
}
getUsers(): Observable<User[]> {
return this.http.get<User[]>(this.apiURLUsers);
}
getUser(userId: string): Observable<User> {
return this.http.get<User>(`${this.apiURLUsers}/${userId}`);
}
createUser(user: User): Observable<User> {
return this.http.post<User>(this.apiURLUsers, user);
}
updateUser(user: User): Observable<User> {
return this.http.put<User>(`${this.apiURLUsers}/${user.id}`, user);
}
deleteUser(userId: string): Observable<any> {
return this.http.delete<any>(`${this.apiURLUsers}/${userId}`);
}
getUsersCount(): Observable<number> {
return this.http
.get<number>(`${this.apiURLUsers}/get/count`)
.pipe(map((objectValue: any) => objectValue.userCount));
}
getCountries(): { id: string; name: string }[] {
return Object.entries(countriesLib.getNames('en', { select: 'official' })).map((entry) => {
return {
id: entry[0],
name: entry[1]
};
});
}
getCountry(countryKey: string): string {
return countriesLib.getName(countryKey, 'en');
}
}
任何帮助将不胜感激。另外值得注意的是,这个错误只会在我更新用户时出现,而不是在我创建/删除时出现。
编辑:这是我的用户方案代码,
型号:
const mongoose = require ('mongoose');
const userSchema = mongoose.Schema ({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
passwordHash: {
type: String,
required: true,
},
phone: {
type: String,
required: true,
},
isAdmin: {
type: Boolean,
default: false,
},
street: {
type: String,
default: ''
},
apartment: {
type: String,
default: ''
},
zip: {
type: String,
default: ''
},
city: {
type: String,
default: ''
},
country: {
type: String,
default: ''
},
})
userSchema.virtual('id').get(function() {
return this._id.toHexString();
});
userSchema.set('toJSON', {
virtuals: true,
});
exports.User = mongoose.model('User', userSchema);
exports.userSchema = userSchema;
和路线:
const express = require('express');
const router = express.Router();
const {User} = require('../models/user');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
//USER POST
router.post(`/`, async (req, res) => {
let user = new User ({
name: req.body.name,
email: req.body.email,
passwordHash: bcrypt.hashSync(req.body.password, 10),
phone: req.body.phone,
isAdmin: req.body.isAdmin,
street: req.body.street,
apartment: req.body.apartment,
zip: req.body.zip,
city: req.body.city,
country: req.body.country,
})
user = await user.save();
if(!user)
return res.status(400).send('the user cannot be created')
res.send(user);
})
//USER GET
router.get(`/`, async (req, res) => {
let userList = await User.find().select('-passwordHash');
if(!userList) {
res.status(500).json({success: false})
}
res.send(userList);
})
router.get('/:id', async(req, res) => {
let user = await User.findById(req.params.id).select('-passwordHash');
if(!user)
res.status(404).json({message: 'user ID not found'});
res.status(200).send(user);
})
router.post('/login', async(req,res) => {
let user = await User.findOne({email: req.body.email})
const secret = process.env.secret;
if(!user) {
return res.status(400).send('The User Not Found');
}
if (user && bcrypt.compareSync(req.body.password, user.passwordHash))
{
const token = jwt.sign(
{
userId: user.id,
isAdmin: user.isAdmin
},
secret,
{expiresIn: '1d'}
)
res.status(200).send({user: user.email, token: token})
} else {
res.status(400).send('password is wrong!')
}
})
//REGISTER
router.post('/register', async (req, res) => {
let user = new User ({
name: req.body.name,
email: req.body.email,
passwordHash: bcrypt.hashSync(req.body.password, 10),
phone: req.body.phone,
isAdmin: req.body.isAdmin,
street: req.body.street,
apartment: req.body.apartment,
zip: req.body.zip,
city: req.body.city,
country: req.body.country,
})
user = await user.save();
if(!user)
return res.status(400).send('the user cannot be created')
res.send(user);
})
//USER DELETE
router.delete('/:id', (req, res) => {
User.findByIdAndRemove(req.params.id).then(user => {
if (user) {
return res.status(200).json({sucess: true, message: 'user deleted successfully'})
} else {
return res.status(404).json({success: false, message: 'user not found'})
}
}).catch (err=> {
return res.status(400).json ({success: false, error: err})
})
})
//USER COUNT
router.get(`/get/count`, async (req, res) => {
const userCount = await User.countDocuments()
if(!userCount) {
res.status(500).json({success: false})
}
res.send ({
usercount: userCount
});
})
module.exports = router;
已解决:
正如有人在评论中指出的那样,我的后端架构中没有 PUT 请求。当我添加放置请求时,它起作用了。