【发布时间】:2022-02-09 02:55:07
【问题描述】:
我正在尝试使用表单将数据发送到 MySQL 数据库中的表。 单击创建按钮时,我仅在 chrome 开发控制台中收到此 error。
我已经通过结合 Jason Watmore 的前端和后端代码来配置这个应用程序,并使用 VS 代码终端命令将项目更新到 Angular 版本 11。 https://jasonwatmore.com/post/2020/08/29/angular-10-boilerplate-email-sign-up-with-verification-authentication-forgot-password
与
项目的所有其他方面都按预期工作,因为我没有编辑它们。 (注册、验证、登录、从其他 MySQL 表更新配置文件数据等)
我的数据库表被称为“实验室交换”,这些 properties。
非常感谢任何帮助或指导,我希望这个问题包含足够的细节。 感谢您的阅读。
前端代码
home.component.html:
<div class="p-4">
<div class="container">
<h1>Welcome {{account.firstName}}!</h1>
<h2>You can create a lab swap request here!</h2>
<!-- <p></p> -->
</div>
</div>
<form [formGroup]="labSwapForm" (ngSubmit)="onSubmit()">
<div class="form-group col-4">
<label>Your Full Name</label>
<input type="text" formControlName="swapCandidateOne" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.swapCandidateOne.errors }" />
<div *ngIf="submitted && f.swapCandidateOne.errors" class="invalid-feedback">
<div *ngIf="f.swapCandidateOne.errors.required">Full Name is required</div>
</div>
</div>
<div class="form-group col-4">
<label>Lab Swap Request Details</label>
<input type="text" formControlName="swapRequestDetail" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.swapRequestDetail.errors }" />
<div *ngIf="submitted && f.swapRequestDetail.errors" class="invalid-feedback">
<div *ngIf="f.swapRequestDetail.errors.required">Lab Swap Details are required</div>
</div>
</div>
<div class="form-group">
<button type="submit" [disabled]="loading" class="btn btn-primary mr-2 mb-3 ml-3">
<span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
Create Lab Swap Request
</button>
</div>
</form>
home.component.ts:
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { AccountService, AlertService, LabSwapService } from '@app/_services';
import { first } from 'rxjs/operators';
@Component({ templateUrl: 'home.component.html' })
export class HomeComponent {
account = this.accountService.accountValue;
labSwap = this.labSwapService.labSwapValue;
loading = false;
submitted = false;
labSwapForm: FormGroup;
constructor(
private accountService: AccountService,
private labSwapService: LabSwapService,
private formBuilder: FormBuilder,
private router: Router,
private alertService: AlertService,
private route: ActivatedRoute,
) { }
ngOnInit() {
this.labSwapForm = this.formBuilder.group({
//id: this.formBuilder.control(null, Validators.required),
swapCandidateOne: this.formBuilder.control(null),
swapRequestDetail: this.formBuilder.control(null)
// swapCandidateOne: [this.labSwap.swapCandidateOne, Validators.required],
// swapRequestDetail: [this.labSwap.swapRequestDetail, Validators.required],
});
}
get f() {
return this.labSwapForm.controls;
}
onSubmit() {
debugger;
// reset alerts on submit
//this.alertService.clear();
// stop here if form is invalid
if (this.labSwapForm.invalid) {
return;
}
this.loading = true;
this.labSwapService.update(this.labSwap.id, this.labSwapForm.value) //id is the issue here!
.pipe(first())
.subscribe({
next: () => {
this.alertService.success('Lab Swap Created successfully', { keepAfterRouteChange: true });
this.router.navigate(['../'], { relativeTo: this.route });
},
error: error => {
this.alertService.error(error);
this.loading = false;
}
});
debugger;
}
}
labSwap.ts(模型):
export class LabSwap {
id: number;
fullNameList: string;
swapRequestDetail: string;
swapCandidateOne: string;
swapCandidateTwo: string;
isSwapComplete: boolean;
}
实验室交换服务.ts:
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject, Observable } from 'rxjs';
import { map, finalize } from 'rxjs/operators';
import { environment } from '@environments/environment';
import { LabSwap } from '@app/_models';
//const baseUrl = `${environment.apiUrl}/accounts`;
const baseUrl = `${environment.apiUrl}/lab-swap`;
//const baseUrl = `${environment.apiUrl}/home`;
@Injectable({ providedIn: 'root' })
export class LabSwapService {
private labSwapSubject: BehaviorSubject<LabSwap>;
public labSwap: Observable<LabSwap>;
constructor(
private router: Router,
private http: HttpClient
) {
this.labSwapSubject = new BehaviorSubject<LabSwap>(null);
this.labSwap = this.labSwapSubject.asObservable();
}
public get labSwapValue(): LabSwap {
return this.labSwapSubject.value;
}
logout() {
this.http.post<any>(`${baseUrl}/revoke-token`, {}, { withCredentials: true }).subscribe();
this.stopRefreshTokenTimer();
this.labSwapSubject.next(null);
this.router.navigate(['/account/login']);
}
getAll() {
return this.http.get<LabSwap[]>(baseUrl);
}
getById(id: string) {
return this.http.get<LabSwap>(`${baseUrl}/${id}`);
}
create(params) {
return this.http.post(baseUrl, params);
}
update(id, params) {
return this.http.put(`${baseUrl}/${id}`, params)
.pipe(map((labSwap: any) => {
// update the current lab swap if it was updated
if (labSwap.id === this.labSwapValue.id) {
// publish updated lab swap to subscribers
labSwap = { ...this.labSwapValue, ...labSwap };
this.labSwapSubject.next(labSwap);
}
return labSwap;
}));
}
}
后端代码
lab-swap.controller.js:
const express = require('express');
const router = express.Router();
const Joi = require('joi');
const validateRequest = require('_middleware/validate-request');
const authorize = require('_middleware/authorize')
const Role = require('_helpers/role');
const accountService = require('./account.service');
const labSwapService = require('./lab-swap.service')
// routes
router.post('/revoke-token', authorize(), revokeTokenSchema, revokeToken);
router.post('/register', labSwapSchema);
router.get('/', authorize(Role.Admin), getAllLabSwaps);
router.get('/:id', authorize(), getLabSwapById);
router.post('/', authorize(Role.Admin), createLabSwapSchema, create);
router.put('/:id', authorize(), updateLabSwapSchema, update);
router.delete('/:id', authorize(), _delete);
module.exports = router;
function labSwapSchema(req, res, next) {
const schema = Joi.object({
//fullNameList: Joi.string().required(),
swapRequestDetail: Joi.string().required(),
swapCandidateOne: Joi.string().required(),
swapCandidateTwo: Joi.string().required(),
isSwapComplete: Joi.boolean().valid(false).required()
});
validateRequest(req, next, schema);
}
function getAllLabSwaps(req, res, next) {
labSwapService.getAllLabSwaps()
.then(labSwaps => res.json(labSwaps))
.catch(next);
}
function getLabSwapById(req, res, next) {
// users can get their own account and admins can get any account
if (Number(req.params.id) !== req.user.id && req.user.role !== Role.Admin) {
return res.status(401).json({ message: 'Unauthorized' });
}
labSwapService.getLabSwapById(req.params.id)
.then(labSwap => labSwap ? res.json(labSwap) : res.sendStatus(404))
.catch(next);
}
function createLabSwapSchema(req, res, next) {
const schema = Joi.object({
fullNameList: Joi.string().required(),
swapCandidateOne: Joi.string().required(),
swapCandidateTwo: Joi.string().required(),
swapRequestDetail: Joi.string().email().required(),
isSwapComplete: Joi.boolean().valid(false).required()
});
validateRequest(req, next, schema);
}
function create(req, res, next) {
labSwapService.create(req.body)
.then(labSwap => res.json(labSwap))
.catch(next);
}
function updateLabSwapSchema(req, res, next) {
const schemaRules = {
swapRequestDetail: Joi.string().empty(''),
swapCandidateOne: Joi.string().empty(''),
swapCandidateTwo: Joi.string().empty(''),
isSwapComplete: Joi.boolean().empty(''),
};
function update(req, res, next) {
// users can update their own account and admins can update any account
if (Number(req.params.id) !== req.user.id && req.user.role !== Role.Admin) {
return res.status(401).json({ message: 'Unauthorized' });
}
labSwapService.update(req.params.id, req.body)
.then(labSwap => res.json(labSwap))
.catch(next);
}
实验室交换服务.js:
const db = require('_helpers/db');
module.exports = {
getAllLabSwaps,
getById,
create,
update,
delete: _delete
};
async function getAllLabSwaps() {
const labSwaps = await db.LabSwap.findAll();
return labSwaps.map(x => basicDetails(x));
}
async function getById(id) {
const labSwap = await getLabSwap(id);
return basicDetails(labSwap);
}
async function create(params) {
const labSwap = new db.LabSwap(params);
labSwap.verified = Date.now();
// save labSwap table
await labSwap.save();
return basicDetails(labSwap);
}
async function update(id, params) {
const labSwap = await getLabSwap(id);
// copy params to Lab Swap and save
Object.assign(labSwap, params);
labSwap.updated = Date.now();
await labSwap.save();
return basicDetails(labSwap);
}
async function _delete(id) {
const labSwap = await getLabSwap(id);
await labSwap.destroy();
}
// helper functions
async function getLabSwap(id) {
const labSwap = await db.LabSwap.findByPk(id);
if (!labSwap) throw 'Lab Swap not found';
return labSwap;
}
function basicDetails(labSwap) {
const { id, title, firstName, lastName, email, role, created, updated, isVerified } = labSwap;
return { id, title, firstName, lastName, email, role, created, updated, isVerified };
}
实验室交换模型.js:
const { DataTypes } = require('sequelize');
module.exports = model;
function model(sequelize) {
const attributes = {
fullNameList: { type: DataTypes.STRING, allowNull: true },
swapRequestDetail: { type: DataTypes.STRING, allowNull: true },
swapCandidateOne: { type: DataTypes.STRING, allowNull: true },
swapCandidateTwo: { type: DataTypes.STRING, allowNull: true },
isSwapComplete: { type: DataTypes.BOOLEAN },
//firstName: { type: DataTypes.STRING, allowNull: false },
//lastName: { type: DataTypes.STRING, allowNull: false },
created: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
updated: { type: DataTypes.DATE },
};
const options = {
// disable default timestamp fields (createdAt and updatedAt)
timestamps: false,
};
return sequelize.define('lab-swap', attributes, options);
}
【问题讨论】:
标签: html mysql node.js angular typescript