我只是想在单击时删除一个项目,我编写了一个代码,但是有错误,我已经坚持了2天。
错误TypeError:this.addedBook.indexOf不是函数
我已经在网站上因为缺少信息而问了一个问题,但我很清楚准确
感谢您的帮助
服务
export class BookService {
url: string = 'http://henri-potier.xebia.fr/books';
public booktype: BookType[];
item: any = [];
constructor(private http: HttpClient) { }
getBookList(): Observable<BookType[]> {
return this.http.get<BookType[]>(this.url);
}
addToBook() {
this.item.push(this.booktype);
}
}
addToBook()在这里添加书,但我不知道如何使用它在我的ts文件中显示添加的书
ts.file
export class PaymentComponent implements OnInit {
addedBook: any = [];
product:any;
constructor(private bookService: BookService) { }
ngOnInit(): void {
this.addedBook = this.bookService.getBookList();
}
delete() {
this.addedBook.splice(this.addedBook.indexOf(this.product), 1);
}
}
html
<div class="product" *ngFor="let book of addedBook | async">
<div class="product-image">
<img [src]="book.cover" alt="book">
</div>
<div class="product-details">
<div class="product-title">{{book.title}}</div>
</div>
<div class="product-price">{{book.price | currency: 'EUR'}}</div>
<div class="product-quantity">
<input type="number" value="1" min="1">
</div>
<div class="product-removal">
<button class="remove-product" (click)="delete()">
Supprimé
</button>
</div>
界面
export interface BookType {
title: string;
price: number;
cover: string;
synopsis: string;
}
答案 0 :(得分:0)
我认为this.bookService.getBookList()
返回Observable
,因此对于您而言,使用async
管道并不是最佳解决方案。您应该只订阅服务器响应,然后将其分配给变量。并且在删除项目后仅重新呈现您的ngFor
。
JS
export class PaymentComponent implements OnInit {
addedBook: any[] = [];
product:any;
constructor(private bookService: BookService) { }
ngOnInit(): void {
// Observable
this.bookService.getBookList().subscribe(response =>{
this.addedBook = response;
});
// Promise
/*
this.bookService.getBookList().then(response=>{
this.addedBook = response;
})*/
}
delete(){
this.addedBook.splice(this.addedBook.indexOf(this.product), 1);
// rerender your array
this.addedBook = [...this.addedBook];
}
}
HTML
<div class="product" *ngFor="let book of addedBook">
<div class="product-image">
<img [src]="book.cover" alt="book">
</div>
<div class="product-details">
<div class="product-title">{{book.title}}</div>
</div>
<div class="product-price">{{book.price | currency: 'EUR'}}</div>
<div class="product-quantity">
<input type="number" value="1" min="1">
</div>
<div class="product-removal">
<button class="remove-product" (click)="delete()">
Supprimé
</button>
</div>
答案 1 :(得分:0)
我会建议类似的东西
服务文件
export class BookService {
url: string = 'http://henri-potier.xebia.fr/books';
//add an observable here
private bookUpdated = new Subject<bookType>();
public booktype: BookType[] = [];//initializa empty array
item: any = [];
constructor(private http: HttpClient) { }
//Ive changet the get method like this
getBookList(){
this.http.get<bookType>(url).subscribe((response) =>{
this.bookType.push(response);//Here you add the server response into the array
//here you can console log to check eg: console.log(this.bookType);
//next you need to use the spread operator
this.bookUpdated.next([...this.bookType]);
});
}
bookUpdateListener() {
return this.bookUpdated.asObservable();//You can subscribe to this in you TS file
}
}
现在,在您的TS文件中,您应该订阅更新侦听器。通常在NgOnInit中完成
类似这样的东西:
export class PaymentComponent implements OnInit {
addedBook: BookType;
product:any;
constructor(private bookService: BookService) { }
ngOnInit(): void {
this.bookService.bookUpdateListener().subscribe((response)=>{
this.addedBook = response;//this will happen every time the service class
//updates the book
});
//Here you can call the get book method
this.bookService.getBookList();
}
delete() {
this.addedBook.splice(this.addedBook.indexOf(this.product), 1);
}
}
基本上,当书籍被更改或更新时,您会订阅。现在,您可以简单地使用addedBook.title或HTML中所需的任何内容。
答案 2 :(得分:0)
更新
我建立了一个特殊的stackblitz,以便您可以看到它的实际效果 这是link;
您不能在splice
流上使用JavaScript Observable
,它不是Array
。
为了能够从流中删除项目,您需要将其(流)与另一个流(在您的情况下)组合在一起,以删除要删除的项目的ID。
所以首先创建2个流
// the $ sign at the end of the variable name is just an indication that this variable is an observable stream
bookList$: Observable<any[]>; // holds bookList stream
deleteBook$ = new Subject<{ id: string }>(); // holds book id stream
现在将从数据库中获得的结果(这是一个可观察的流)传递给刚刚创建的bookList$
流
ngOnInit(): void {
this.bookList$ = this.bookService.getBookList().pipe(
delay(0)
);
}
将您的html
模板更改为该模板。并通过管道将结果从数据库中抽取出来
<div class="product" *ngFor="let book of (bookList$ | sync)">
...
// make sure you include your`remove-product` button inside `*ngFor` loop so you can pass the `book id` you want to remove to the `delete()` function.
<button class="remove-product" (click)="delete(book)">
Supprimé
</button>
</div>
现在回到您的ts
文件中,我们将通过修改Array并返回新流从STREAM中删除该项目。
bookList$: Observable<any[]>; // holds bookList stream
deleteBook$ = new Subject<{ id: string }>(); // holds book id stream
ngOnInit(): void {
this.bookList$ = this.this.bookService.getBookList().pipe(
delay(0)
);
combineLatest([
this.bookList$,
this.deleteBook$
]).pipe(
take1(),
map(([bookList, deleteBook]) => {
if (deleteBook) {
var index = bookList.findIndex((book: any) => book.id === deleteBook.id);
if (index >= 0) {
bookList.splice(index, 1);
}
return bookList;
}
else {
return bookList.concat(deleteBook);
}
})
).subscribe();
}
现在剩下要做的就是删除项目
delete(book: any) {
this.deleteBook$.next({ id: book.id }); pass the book you want to remove to the stream, `combineLatest` will take care of the rest
}
如果您要退出,请不要忘记我:) 祝你好运!
答案 3 :(得分:0)
从您的代码中,我们可以看到getBookList()
返回了一个Observable。由于addedBook
不是数组引用,因此将没有数组方法。这就是造成您问题的原因。
如果要从服务数据中进行某些操作,请订阅可观察对象并将该值的引用存储到addedBook
。
导出类PaymentComponent实现OnInit {
...
ngOnInit(): void {
this.bookService.getBookList().subscribe(
res => { this.addedBook = res }
);
}
...
}
您需要从html中删除async关键字
Typescript主要用于在编译时识别此类问题。它不会在编译时引发错误的原因是您已将addedBook
指定为任意值。在声明您将其声明为数组和onInit时,将其更改为可观察的,如果您已指定type[]
例如:string[]