删除商品购物车角度

时间:2020-11-06 21:28:27

标签: javascript angular typescript

我只是想在单击时删除一个项目,我编写了一个代码,但是有错误,我已经坚持了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;
}

4 个答案:

答案 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[]

可以避免