【问题标题】:remove item shopping cart angular删除物品购物车角度
【发布时间】:2020-11-08 06:59:09
【问题描述】:

我只是想在点击时删除一个项目,我做了一个代码但我有错误,我已经卡了 2 天了。

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

【问题讨论】:

  • this.bookService.getBookList() 返回什么?
  • @amerenderSingh 显示来自 api 的数据
  • 您正在使用异步管道来获取添加的书籍,这可能意味着添加的书籍不是数组而是数组的可观察对象(即使看起来它正在初始化为组件?),所以这可能就是您收到错误的原因。你能添加服务的代码吗?这会给它带来一些光明。

标签: javascript angular typescript


【解决方案1】:

我认为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>

【讨论】:

    【解决方案2】:

    更新

    我构建了一个特殊的 stackblitz,以便您可以看到它的实际效果 这是link;

    您不能在Observable 流上使用javascript splice,它不是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 文件,我们将通过修改数组从 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】:

      从您的代码中,我们可以看到 getBookList() 返回一个 Observable。由于addedBook 不是数组引用,它不会有数组方法。这就是你的问题的原因。

      如果你想对服务数据做一些操作,订阅 observable 并将值的引用存储到addedBook

      导出类 PaymentComponent 实现 OnInit {

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

      而且你需要从你的 html 中移除 async 关键字

      Typescript 主要用于在编译时识别这类问题。它不会在编译时抛出错误的原因是您已将 addedBook 指定为 any。在声明时将其声明为数组并在 onInit 中将其更改为可观察的,如果您指定了 type[] 例如:string[]

      ,则可以避免这种情况

      【讨论】:

        【解决方案4】:

        我会建议这样的事情

        服务文件

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

        基本上发生的事情是当书籍更改或更新时您订阅了。现在您可以简单地在 HTML 中使用 addedBook.title 或任何您想要的内容。

        【讨论】:

        • 感谢您的帮助,this.bookUpdated.next([...this.bookType]);我有这个错误:“BookType []”类型的参数不可分配给“BookType”类型的参数。在 ts 文件中我需要 import splice & indexOf ?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-05
        • 1970-01-01
        • 2020-02-17
        • 1970-01-01
        • 2022-08-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多