简体   繁体   English

删除项目购物车角度

[英]remove item shopping cart angular

I would simply like to delete an item on click, I made a code but I have error, I've been stuck on it for 2 days.我只想在点击时删除一个项目,我制作了一个代码,但我有错误,我已经坚持了 2 天。

ERROR TypeError: this.addedBook.indexOf is not a function错误类型错误:this. addedBook.indexOf 不是函数

I have already asked the question on the site we closed it for lack of information yet I am clear and precise我已经在我们关闭的网站上问过这个问题,因为缺乏信息,但我很清楚准确

Thank you for your help感谢您的帮助

service服务

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() here for add book but i dont know how to use it to display added books in my ts file 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 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>

interface界面

export interface BookType {
    title: string;
    price: number;
    cover: string;
    synopsis: string;
}

I think this.bookService.getBookList() returns Observable so for you case it is not the best solution use async pipe.我认为this.bookService.getBookList()返回Observable所以对于你来说它不是使用async管道的最佳解决方案。 You should simply subscribe to your server response and than asign it to your variable.您应该简单地订阅您的服务器响应,而不是将其分配给您的变量。 and after deleting item only rerender your ngFor .删除项目后只重新渲染你的ngFor

JS 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 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>

I would suggest something like this我会建议这样的

Service file服务文件

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
    }
}

Now in your TS file you should subscribe to the update listener.现在在您的 TS 文件中,您应该订阅更新侦听器。 This is typically done in NgOnInit这通常在 NgOnInit 中完成

Something like this:像这样的东西:

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);
      }
    }

Essentially what happens is you are subscribed to when books get changed or updated.本质上,当书籍更改或更新时,您会订阅。 Now you can simply use addedBook.title or whatever you want in your HTML.现在您可以简单地在 HTML 中使用 addedBook.title 或任何您想要的内容。

UPDATE更新

I built a special stackblitz so you can see it in action here is the link ;我构建了一个特殊的 stackblitz,因此您可以在此处查看它的运行情况,这是链接

you can't use javascript splice on Observable stream, it is not an Array .你不能在Observable流上使用 javascript splice ,它不是一个Array
to be able to remove an item from a stream you need to combine it (the stream) with another stream (in your case) the id of the item you want to remove.为了能够从流中删除项目,您需要将它(流)与另一个流(在您的情况下)要删除的项目的 ID 结合起来。

so first create 2 streams所以首先创建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

now pass the results you get from your database (which is an observable stream) to bookList$ stream you just created like that现在将从您的数据库(这是一个可观察的流)获得的结果传递给您刚刚创建的bookList$

ngOnInit(): void {

    this.bookList$ = this.bookService.getBookList().pipe(
        delay(0)
    );

}

change your html template to that.. and pipe the results from database like that将您的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>

now back to your ts file where we gonna remove the item from the STREAM by modifying the Array and return a new stream.现在回到你的ts文件,我们将通过修改数组从 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();

} }

now all is left to do is remove the item现在剩下要做的就是删除该项目

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
}

if you make an exit please don't forget me :) good luck!如果您退出,请不要忘记我:) 祝您好运!

From your code, we can see that getBookList() return an Observable.从您的代码中,我们可以看到getBookList()返回一个 Observable。 As addedBook is not a array reference it will won't have array methods.由于addedBook不是数组引用,因此不会有数组方法。 That is the cause for your issue.这就是你的问题的原因。

If you want to do some operations from the service data, subscribe to the observable and store the reference of the value to addedBook .如果你想对服务数据做一些操作,订阅 observable 并将值的引用存储到addedBook

export class PaymentComponent implements OnInit {导出类 PaymentComponent 实现 OnInit {

  ...

  ngOnInit(): void {
    this.bookService.getBookList().subscribe(
        res => { this.addedBook = res }  
    );
  }

  ...
}

And you need to remove the async keyword from your html并且您需要从 html 中删除 async 关键字

Typescript is mainly used to identify these kind of issues in compile time. Typescript 主要用于在编译时识别此类问题。 The reason it doesn't throw error on compile time is that you've specified addedBook as any.它不会在编译时抛出错误的原因是您已将addedBook指定为 any。 While declaring you declare it as array and onInit you change it to observable, which can be avoided if you've specified type[] ex: string[]在声明您将其声明为数组和 onInit 时,您将其更改为 observable,如果您已指定type[]例如: string[] ,则可以避免这种情况

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM