订阅返回未定义的事件发射器

时间:2020-03-27 16:17:17

标签: angular

我正在尝试允许用户从我的食谱应用程序的购物清单中的一系列食材中删除食材。我创建了一个事件发射器,当用户单击“删除”按钮时将触发该事件。我订阅了该事件,但是出现了以下错误消息:“无法读取未定义的属性'subscribe'”。

我相信我将遇到的另一个问题是“成分”(这是我得到的事件数据)不是数字。当我在拼接方法中使用它时,我认为这不会起作用。希望有人可以帮忙。

以下是相关的html代码:

<div *ngIf="ingredients.length > 1">
    <div class="shopping-list-container">
        <img src="https://i.ya-webdesign.com/images/shopping-cart-icon-png-1.png" class="shopping-cart-image" alt="shopping cart">
        <ul>
            <li *ngFor="let ingredient of ingredients" class="shopping-list row">
                {{ ingredient.name }} - {{ ingredient.amount }}
                <img (click)="onDeleteItem(ingredient)" src="https://getdrawings.com/free-icon/delete-all-icon-63.png" alt="delete" class="delete-image">
            </li>
        </ul>
    </div>
</div>

这是在.service文件中创建的事件发射器(我仅在此处包括相关位):

import { EventEmitter } from '@angular/core';

@Injectable({
  providedIn: 'root'
})



  export class ShoppingListService {

   deleteItem = new EventEmitter<Ingredient>();

  }

这是.component文件(同样,我只包含了相关内容):

import { ShoppingListService } from './shopping-list.service';

export class ShoppingListComponent implements OnInit {

ingredients: Ingredient[];

constructor(private shoppingListService: ShoppingListService) { }

ngOnInit() {

   this.shoppingListService.deleteItem.subscribe( 
      (ingredient: number) => {
        this.ingredients.splice(ingredient, 1);
      }
    );
  }

  onDeleteItem(ingredient) {
    this.shoppingListService.deleteItem.emit(ingredient)
  }

}

}

1 个答案:

答案 0 :(得分:2)

您不应在服务中使用EventEmitter,仅用于components

相反,您需要按以下方式使用ObservableBehaviorSubject/Subject

@Injectable({
  providedIn: 'root',
})
export class ShoppingListService { 
  itemDeleted : Subject<Ingredient> = new Subject<Ingredient>();
  private itemDeleted$: Observable<Ingredient> = this.itemDeleted.asObservable();

  deleteItem(item:Ingredient) {
    this.itemDeleted.next(item);
  }

}

在您的组件中

private unsubcribeAll: Subject<any> = new Subject<Any>();

ngOnInit() {

   this.shoppingListService.itemDeleted
   .pipe(
      takeUntil(this.unsubcribeAll)
    )
   .subscribe((ingredient: Ingredient) => {
        // this.ingredients.splice(ingredient, 1);
   });
}

ngOnDestroy() {
  this.unsubscribeAll.next();
  this.unsubscribeAll.complete();
}

onDeleteItem(ingredient) {
    this.shoppingListService.deleteItem(ingredient);
}

}
上面的代码中的

unsubcribeAll用于防止内存泄漏和取消订阅的情况

解决方案2

如果您的组件位于同一层次结构中,则不需要服务来通知操作。

例如

recipe.component

<section>
   <app-ingredient-list [ingredients]="recipeIngredients" (itemDeleted)="onItemDeleted($event)"></app-ingredient-list>
</section>

receipe.component.ts

  onItemDeleted(item:Ingredient) {
     // do what is needed here
  }

ingredient-list.component.ts

  @Output() itemDeleted: EventEmitter<Ingredient> = new EventEmitter<Ingredient>();

  onDeleteButtonClick(item: Ingredient) {
    this.itemDeleted.emit(item);
  }