【问题标题】:Subscribing to event created and emitted from a service订阅从服务创建和发出的事件
【发布时间】:2020-03-22 19:37:29
【问题描述】:

我正在尝试使用组件订阅事件,以从我创建的服务发出的事件中获取数据。我对 Angular 很陌生,我正在努力解决这个问题!当用户从食谱列表中选择一个食谱时,应显示完整的食谱(包括配料)。目前我正在将选定的配方记录到控制台,但我只是得到我在模型文件中制作的构造函数

这里是 recipes.html 文件:

<div *ngFor="let recipe of recipes" class="list-item">
    <a 
    href="#"
    class="list-group-item clearfix"
    (click)="onRecipeSelected(recipe)">
    <img 
        [src]="recipe.imagePath" 
        alt="{{ recipe.name }}"
        class="img-responsive">
    <div class="pull-left">
        <h4 class="list-group-item-heading item-text">{{ recipe.name }}</h4>
        <p class="list-group-item-text item-text">{{ recipe.description }}</p>
    </div>
</a>
</div>  

这里是 recipes.ts 文件:

import { Component, OnInit, Input } from '@angular/core';
import { Recipe } from './recipes.model';
import { Recipeservice } from './recipes.service';

@Component({
  selector: 'app-recipes',
  templateUrl: './recipes.component.html',
  styleUrls: ['./recipes.component.css'],
})
export class RecipesComponent implements OnInit {
  recipes: Recipe[];

  constructor(private recipeService: Recipeservice) {}

 onRecipeSelected(recipe: Recipe) {
    this.recipeService.RecipeSelected.emit(recipe);
    console.log(Recipe);
}

  ngOnInit() {
    this.recipes = this.recipeService.getRecipes();
  }

}

这里是 recipes.service 文件:

import { Recipe } from './recipes.model';
import { Ingredient } from '../shared/ingredient.model';
import { Injectable } from '@angular/core';
import { EventEmitter } from '@angular/core';

@Injectable()
export class Recipeservice {

RecipeSelected = new EventEmitter<Recipe>();


    private recipes: Recipe[] = [
        new Recipe('Spaghetti Carbonara', 'Authentic Italian Carbonara', 'https://d1doqjmisr497k.cloudfront.net/-/media/schwartz/recipes/2000x1125/easy_spaghetti_carbonara_2000.jpg?vd=20180522T020207Z&hash=9B103A2DB3CDCB31DB146870A3E05F9856C051A2', [
            new Ingredient('Spaghetti', 500),
            new Ingredient('Lardons', 20),
            new Ingredient('egg', 4),
            new Ingredient('parmesan', 100),
            new Ingredient('Garlic', 1),
            new Ingredient('Olive Oil', 50)
        ]),

        new Recipe('Lasagne', 'Mums lasagne recipe', 'https://img.taste.com.au/bBe9SZ5Q/taste/2016/11/cheesy-beef-and-spinach-lasagne-45846-1.jpeg', [
            new Ingredient('Spaghetti', 500),
            new Ingredient('Lardons', 20),
            new Ingredient('egg', 4),
            new Ingredient('parmesan', 100),
            new Ingredient('Garlic', 1),
            new Ingredient('Olive Oil', 50)
        ])
    ];



        getRecipes() {
            return this.recipes.slice();
        }

}

这是 recipe-view.ts 文件(我订阅事件的地方):

import { Component, OnInit } from '@angular/core';
import { Recipeservice } from '../recipes/recipes.service'
import { Recipe } from '../recipes/recipes.model';

@Component({
  selector: 'app-recipe-view',
  templateUrl: './recipe-view.component.html',
  styleUrls: ['./recipe-view.component.css'],
  providers: [Recipeservice]
})
export class RecipeViewComponent implements OnInit {
  selectedRecipe: Recipe;

  constructor(private recipeService: Recipeservice) { }

  ngOnInit() {
    this.recipeService.RecipeSelected.subscribe(
      (recipe: Recipe) => {
        this.selectedRecipe = recipe;
console.log(this.selectedRecipe);
      }
    );
  }

}

最后是 recipe-view.html 文件:

<div class="recipe-full-view">
    <h4 class="list-group-item-heading">{{ selectedRecipe.name }}</h4>
    <p class="list-group-item-text">{{ selectedRecipe.description }}</p>
</div>
<ul class="Ingredients-list">
    <li class="Ingredients-list-item"
    *ngFor="let Ingredient of selectedRecipe.ingredients">
    {{ Ingredient.name }} - {{ Ingredient.amount }}
</li>
</ul>

您能给我的任何帮助将不胜感激,因为我现在有点失落! P.s '新配方'来自一个模型文件,我没有包括在内,因为我觉得它不相关。

【问题讨论】:

    标签: angular


    【解决方案1】:

    在你的recipes.html中,你应该调用一个名为onRecipeSelected()的方法:

    <div *ngFor="let recipe of recipes" class="list-item">
        <a href="#" ... (click)="onRecipeSelected(recipe)">
        ...
    

    在“recipes.ts”中,调用RecipeService 方法选择食谱:

    export class RecipesComponent implements OnInit {
      ...
    
      onRecipeSelected(recipe: Recipe) {
        this.recipeService.selectRecipe(recipe);
      }
    }
    

    我建议您对代码进行一些改进,尤其是在 RecipeService 中,使用 BehaviorSubject 代替 EventEmitter

    @Injectable()
    export class RecipeService {
      private recipes = [....];
    
      selectedRecipe$ = new BehaviorSubject<Recipe>(null);
      recipes$ = new BehaviorSubject<Recipe[]>(this.recipes);
    
      selectRecipe(recipe: Recipe) {
        this.selectedRecipes.next(recipe);
      }
    }
    

    因此您的RecipeViewComponent 代码可以更改为:

    export class RecipeViewComponent implements OnInit {
      selectedRecipe$: Observable<Recipe>;
    
      constructor(private recipeService: RecipeService) { }
    
      ngOnInit() {
        this.selectedRecipe$ = this.recipeService.selectedRecipe$;
      }
    }
    

    我为您的用例制作了simplified Stackblitz demo。它演示了ObservableBehaviorSubject 的使用。

    【讨论】:

    • 感谢您的回复。我现在尽量不要让自己更加困惑,所以我暂时不要使用 BehaviorSubject 并坚持使用事件发射器。我已经对我的代码进行了一些更改,但是现在当我将“selectedRecipe”记录到控制台时,我只会得到我在模型文件中创建的构造函数,而不是实际的 selectedRecipe。我将修改我的 OP 以反映更改
    猜你喜欢
    • 2018-01-03
    • 2018-10-07
    • 2016-04-30
    • 1970-01-01
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 2019-12-17
    • 1970-01-01
    相关资源
    最近更新 更多