0

I have the main component which is called app.component and a sub component if I am allowed to call it like that called items.component.

The script of app.component is:

import { Component, EventEmitter, Output } from '@angular/core';
import { ItemsClass } from './items-class';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  list:ItemsClass = new ItemsClass('Product 1', 'Electronics', 'Sold Out');
  @Output() EmitData = new EventEmitter<ItemsClass>();

  onSelected(list:ItemsClass){

    this.EmitData.emit(list);

  }
}

Where onSelected() method will help me to send data to the sub component and display it, when a user click on an item displayed on app.component.

Here is the script of items.component:

import { Component, OnInit } from '@angular/core';

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

  constructor() { }

  ngOnInit() {
  }
}

Now here is the HTML of app.component:

<div class="col-md-4" >
    <a class="btn btn-success">New Recipe</a>
</div>
<a href="#" class="list-group-item clearfix">
<hr>
  <div class="col-md-4">
    <ul class="list-group">
    {{list.name}}
    </ul> 
    {{list.desc}} | {{list.stat}}
  </div>
</a>
<app-items (click)="onSelected(list)"></app-items>

items.component.html:

<div class="row">
  <div class="col-xs-12">
    <img src="{{list.stat}}" alt="" class="img-responsive">
  </div>
</div>
<div class="row">
  <div class="col-xs-12">
    <h1>{{list.name}}</h1>
  </div>
  <div class="col-xs-12">
    <button class="btn btn-success">To Shopping List</button>
    <button class="btn btn-primary">Edit</button>
    <button class="btn btn-danger">Delete</button>
  </div>
</div>
<hr>
<div class="row">
  <div class="col-xs-12">
    <p>{{list.desc}}</p>
  </div>
</div>
<div class="row">
  <div class="col-xs-12">
    Ingredients
  </div>
</div>

I am getting the following error when I click on the Product 1 row (which is displayed properly by the class ItemsClass:

EXCEPTION: Error in ./ItemsComponent class ItemsComponent - inline template:2:9 caused by: Cannot read property 'stat' of undefined

I am new to angular 2 and it is a little bit complicated.

alim1990
  • 4,656
  • 12
  • 67
  • 130

1 Answers1

1

You are getting this error because ItemsComponent (the TypeScript class) does not have a list property.

If you have some experience with e.g. Angular 1, you need to realize that in Angular 2+ basically each component has isolate scope and does not have access to ancestor scopes.

To fix this, in app.component.html you need:

<app-items [list]="list" (click)="onSelected(list)"></app-items>

Then in items.component.ts:

export class ItemsComponent {
    @Input() list;
}

This way "app component" will pass the value to the "items component".

Konrad Garus
  • 53,145
  • 43
  • 157
  • 230
  • Because we are getting the list variable from another component we should set it as input right ? Can you explain more ? – alim1990 Jan 20 '17 at 16:51
  • Everything that an HTML template has access to has to be a property of its TS controller. There is nothing like "scope inheritance", each component is isolated and has to obtain the data from "somewhere". Let me know if you have more specific questions... – Konrad Garus Jan 20 '17 at 17:41
  • Now the problem is that the data are shown without clicking so the (click) event isn't fired but I am seeing the result on screen. Any help. – alim1990 Jan 23 '17 at 06:21