angular - 在Angular 8中传递包含文本和图像的FormData时出错
问题描述
我有一个 Angular 表单,我在其中输入一些文本字段和一个图像字段,我将它们与 FormData() 捆绑在一起,然后将它们传递给我的服务。
这是我的 HTML 文件:-
<body>
<a routerLink="/"><img id="mainLogo" src="../../assets/images/main-logo-resized.PNG" alt="Go to main page"></a>
<input type="button" id="logoutBtn" (click)="onLogout()" value="Logout">
<div class="genericForm">
<form #sellBookForm="ngForm" enctype="multipart/form-data" (ngSubmit)="sellBookForm.valid && onSubmit(sellBookForm)">
<h1>Tell us about your book</h1>
<input type="text" #bookName="ngModel" [(ngModel)]="bookService.selectedBook.bookName" name="bookName" placeholder="Name of book" required autofocus [ngClass]="{'invalid-textbox': sellBookForm.submitted && !bookName.valid}">
<div *ngIf="sellBookForm.submitted && !bookName.valid">
<label class="validation-message">This field is required!</label>
</div>
<br>
<input type="text" #authorName="ngModel" [(ngModel)]="bookService.selectedBook.authorName" name="authorName" placeholder="Name of author" required [ngClass]="{'invalid-textbox': sellBookForm.submitted && !authorName.valid}">
<div *ngIf="sellBookForm.submitted && !authorName.valid">
<label class="validation-message">This field is required!</label>
</div>
<br>
<input type="text" #publisherName="ngModel" [(ngModel)]="bookService.selectedBook.publisherName" name="publisherName" placeholder="Name of publisher" required [ngClass]="{'invalid-textbox': sellBookForm.submitted && !publisherName.valid">
<div *ngIf="sellBookForm.submitted && !publisherName.valid">
<label class="validation-message">This field is required!</label>
</div>
<br>
<input type="text" #price="ngModel" [(ngModel)]="bookService.selectedBook.price" name="price" placeholder="Price" required ngClass="{'invalid-textbox': sellBookForm.submitted && !price.valid}">
<div *ngIf="sellBookForm.submitted && !price.valid">
<label class="validation-message">This field is required!</label>
</div>
<br>
<input type="file" #bookImg="ngModel" [(ngModel)]="bookService.selectedBook.bookImg" name="bookImg" accept="image/*" id="bookImg" (change)="onFileSelected($event)" required ngClass="{'invalid-textbox': sellBookForm.submitted && !bookImg.valid}">
<label for="bookImg" id="bookImgLabel"><img src="../../assets/images/upload-image-resized.png" alt="Upload">Upload book image</label>
<div *ngIf="sellBookForm.submitted && !bookImg.valid">
<label class="validation-message">This field is required!</label>
</div>
<br>
<input type="submit" value="Sell now!">
</form>
</div>
<a routerLink="/marketplace" class="backToMarketplaceLink">Back to marketplace</a>
</body>
这是我的组件文件:-
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { UserService } from '../shared/user.service';
import { BookService } from '../shared/book.service';
import { NgForm } from '@angular/forms';
@Component({
selector: 'app-sell-page',
templateUrl: './sell-page.component.html',
styleUrls: ['./sell-page.component.css']
})
export class SellPageComponent implements OnInit {
// Variable to get the book image file
bookImg;
// Boolean variable to show/hide div element is case of successful book submission
showSuccessMessage: boolean;
// Error messages in case book submission failed
serverErrorMessages: string;
constructor(private userService: UserService, private bookService: BookService, private router: Router) { }
ngOnInit() {
}
onFileSelected(event) {
this.bookImg = event.target.files[0];
document.getElementById('bookImgLabel').innerHTML = this.bookImg.name;
}
onSubmit(form: NgForm) {
const formData = new FormData();
formData.append('bookData', JSON.stringify(form.value));
formData.append('bookImg', this.bookImg, this.bookImg.name);
this.bookService.postBook(formData).subscribe(
res => {
this.showSuccessMessage = true;
setTimeout(() => {
this.showSuccessMessage = false;
}, 1000);
},
err => {
if (err.status === 422) {
this.serverErrorMessages = err.error.join('<br/>');
} else {
this.serverErrorMessages = 'Oops! Something went wrong. Please try again.';
}
}
);
}
onLogout() {
this.userService.deleteToken();
this.router.navigateByUrl('/login');
}
}
我收到一个错误this.bookService.postBook(formData).subscribe()
:-
Argument of type 'FormData' is not assignable to parameter of type 'Book'.
Type 'FormData' is missing the following properties from type 'Book': bookName, authorName, publisherName, price, bookImg
这是我的服务文件:-
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Book } from './book.model';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class BookService {
selectedBook: Book = {
bookName: '',
authorName: '',
publisherName: '',
price: 0,
bookImg: null
};
constructor(private http: HttpClient) { }
// HTTP methods
postBook(book: Book) {
return this.http.post(environment.baseUrl + '/sell', book);
}
}
此服务文件正在使用模型类文件:-
export class Book {
bookName: string;
authorName: string;
publisherName: string;
price: number;
bookImg: File;
}
我不明白为什么会出现此错误,因为我已将整个表单值与图像文件一起附加到formData
组件文件的变量中。我不能将 FormData() 与模型一起使用来传递信息吗?请帮忙,我是Angular的新手。
解决方案
在 BookService 的 postBook 方法中,您期望 Parameter 类型为 Book Class ,但您在组件中使用 FormData 。有很多方法可以解决这个问题:
- 在 postBook 中将参数类型更改为 FormData。
- 您可以在服务中使用 selectedBook 字段,因为您在其中绑定了值,除了需要单个 formData 的 img 。
推荐阅读
- javascript - 如何在 react/redux web 应用程序中持久化数据?
- ruby - 了解方法中错误的影响
- r - 重新排列不平衡的时间序列数据
- javascript - JavaScript localStorage 在页面加载后无法保存数据
- regex - 正则表达式查找带引号、分号和等于的值
- mysql - 当表的名称带有下划线时,PDO 在获取时返回 false
- c# - 构建干净的 Nuget2 存储库会出错
- tensorflow - Tensorflow 在多 GPU 训练中一次只有一个 GPU 处于活动状态
- javascript - 单选按钮输入上的“checked”属性不存在
- dc.js - 如何在不破坏过滤器的情况下在 crossfilter.js 中向前移动组的值