0
votes

I have three components in my angular app namely RecipeBook, RecipeList and RecipeItem. Recipe Book contains Recipe List in which there are 'n' number of recipe items. and there is another component namely RecipeDetail. So, I want to display RecipeDetail component only if one of the RecipeItem is clicked.

The component should appear in the place of "Please select a recipe"

enter image description here

recipe-item-component.html :

        <a href="#" class="list-group-item clearfix" (click)="onClick()">
      <div class="pull-left">
        <h4 class="list-group-item-heading">{{ recipe.name }}</h4>
        <p class="list-group-item-text">{{ recipe.description }}</p>
      </div>
      <span class="pull-right">
        <img
          src="{{ recipe.imageUrl }}"
          alt="{{ recipe.name }}"
          class="responsive"
          style="max-height: 50px;"
        />
      </span>
    </a>

recipe-item-component.ts:

import { Component, OnInit, Input, Output, EventEmitter } from "@angular/core";
    import { Recipe } from "../../recipe.model";
    import {} from "protractor";
    
    @Component({
      selector: "app-recipe-item",
      templateUrl: "./recipe-item.component.html",
      styleUrls: ["./recipe-item.component.css"]
    })
    export class RecipeItemComponent implements OnInit {
      @Input() recipe: Recipe;
      @Output() clicked = new EventEmitter<void>();
      constructor() {}
    
      ngOnInit() {}
    
      onClick() {
        this.clicked.emit();
      }
    }

recipe-list.component.html:

        <div class="row">
      <div class="col-xs-12">
        <button class="btn btn-success">New Recipe</button>
      </div>
      <hr>
    </div>
    <div class="row">
      <div class="col-xs-12">
          <hr>
          <app-recipe-item *ngFor="let recipeEl of recipes" [recipe]="recipeEl"
          (onclick)="onRecipeSelect(recipeEl)"></app-recipe-item>

      </div>
    </div>

recipe-list.component.ts:

        import { Component, OnInit, Output, EventEmitter } from '@angular/core';
    import { Recipe } from '../recipe.model';
    
    @Component({
      selector: 'app-recipe-list',
      templateUrl: './recipe-list.component.html',
      styleUrls: ['./recipe-list.component.css']
    })
    export class RecipeListComponent implements OnInit {
      @Output() recipeSelected = new EventEmitter<Recipe>();
      recipes : Recipe[] =[
        // First Recipe
        new Recipe("First Recipe", "This is my first recipe" ,
      "https://www.gimmesomeoven.com/wp-content/uploads/2014/03/Cajun-Jambalaya-Recipe-with-Andouille-Sausage-Shrimp-and-Chicken-3-1.jpg"),
        // Second Recipe
        new Recipe("Second Recipe", "This is my second recipe" ,
        "https://www.tasteofhome.com/wp-content/uploads/2017/10/Healthier-than-Egg-Rolls_EXPS_SDON17_55166_C06_23_6b-696x696.jpg"),
        // Third recipe
        new Recipe("Third Recipe", "This is my third recipe" ,
        "https://www.wellplated.com/wp-content/uploads/2017/12/Hoppin-John-recipe-600x629.jpg"),
    ];        
      constructor() {
    
      }
    
      ngOnInit() {
      }
      onRecipeSelect(recipe : Recipe){
            this.recipeSelected.emit(recipe);
       }
    }

recipe-book.component.html:

        <div class="row">
      <div class="col-md-5">
        <app-recipe-list (recipeSelected)="selectedRecipe = $event"></app-recipe-list>
      </div>
      <div class="col-md-7">
        <app-recipe-detail *ngIf="selectedRecipe; else noRecipe"></app-recipe-detail>
        <ng-template #noRecipe>
          Please Select a recipe
        </ng-template>
      </div>
    </div>

recipe-book.component.ts:

import { Component, OnInit } from '@angular/core';
    import { Recipe } from './recipe.model';
    
    @Component({
      selector: 'app-recipe-book',
      templateUrl: './recipe-book.component.html',
      styleUrls: ['./recipe-book.component.css']
    })
    export class RecipeBook implements OnInit {
       selectedRecipe: Recipe;
    
    
      constructor() { }
    
      ngOnInit() {
      }
    
    }

So, my requirement is to make the RecipeDetail component to be visible only if the selected recipe is true. I believe I followed the approach correctly but, the property selectedRecipe is undefined even though I clicked on the recipe item.

Steps I followed :

  • Created a dummy click event in recipe event to let know the recipe list abput the click

  • emitted the actual recipe event from the recipe list component.

  • listened it in recipe book component and assigned the selectedRecipe property my recipe value.

    The selectedRecipe property stays undefined throughout the execution which in turn not letting the Recipe Detail component to appear

2
Please create a minimum reproduction on stackblitz - Sachin Gupta

2 Answers

0
votes

You should change onclick to clicked, because your recipe-item component emitting clicked event but you are listening for onclick. That might be your problem. Try to change it.

<div class="row">
  <div class="col-xs-12">
    <button class="btn btn-success">New Recipe</button>
  </div>
  <hr>
</div>

<div class="row">
  <div class="col-xs-12">
      <hr>
      <app-recipe-item *ngFor="let recipeEl of recipes" [recipe]="recipeEl"
      (clicked)="onRecipeSelect(recipeEl)"></app-recipe-item>
  </div>
</div>
0
votes

use (click)="onRecipeSelect(recipeEl)" instead of `(onclick)="onRecipeSelect(recipeEl)"