Max Bertoli
Max Bertoli

Reputation: 614

Error during data binding: property is null

I have a component list and its child (component item). I'm trying to pass information from list to item, but it seem data binding doesn't work because the object is null, even if i have (hope) correctly initialized.

This is the list component with its own template:

import { Component, OnInit, Output, EventEmitter } from '@angular/core';
import { Recipe } from '../recipe';
import { RecipeItemComponent } from './recipe-item.component';

@Component({
  selector: 'app-recipe-list',
  templateUrl: './recipe-list.component.html',
  styles: []
})

export class RecipeListComponent implements OnInit {
  @Output() recipeSelected = new EventEmitter<Recipe>();
  recipes: Recipe[] = [];
  public recipe: Recipe;

  constructor() {
    this.recipe = new Recipe('Dummy', 'Dummy', 'http://thumbs1.ebaystatic.com/d/l225/m/mfXELL6zPWJE4OC0agiXMZw.jpg');
  }

  ngOnInit() {
  }

  onSelected(recipe: Recipe) {
    this.recipeSelected.emit(recipe);
  }
}

<div class="row">
  <div class="col-xs-12">
    <a class="btn btn-success">New Recipe</a>
  </div>
</div>
<div class="row">
  <div class="col-xs-12">
    <ul class="list-group">
      <app-recipe-item> [recipe]="recipe" (click)="onSelected(recipe)"></app-recipe-item>
    </ul>
  </div>
</div>

And here the component item:

import { Component, OnInit, Input } from '@angular/core';
import { Recipe } from '../recipe';

@Component({
  selector: 'app-recipe-item',
  templateUrl: './recipe-item.component.html',
  styles: []
})
export class RecipeItemComponent implements OnInit {
  @Input() recipe: Recipe;
  recipeId: number;

  constructor() { 

  }

  ngOnInit() {
  }
}

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

The error:

Unhandled Promise rejection: Error in ./RecipeItemComponent class RecipeItemComponent - inline template:2:40 caused by: Cannot read property 'name' of undefined ; Zone: <root> ; Task: Promise.then ; Value:
ViewWrappedError
Error: Error in ./RecipeItemComponent class RecipeItemComponent - inline template:2:40 caused by: Cannot read property 'name' of undefined
    at ViewWrappedError.ZoneAwareError (http://localhost:4200/polyfills.bundle.js:6880:33)
    at ViewWrappedError.BaseError [as constructor] (http://localhost:4200/vendor.bundle.js:24986:16)
    at ViewWrappedError.WrappedError [as constructor] (http://localhost:4200/vendor.bundle.js:25051:16)
    at new ViewWrappedError (http://localhost:4200/vendor.bundle.js:53759:16)
    at CompiledTemplate.proxyViewClass.DebugAppView._rethrowWithContext (http://localhost:4200/vendor.bundle.js:72648:23)
    at CompiledTemplate.proxyViewClass.DebugAppView.detectChanges (http://localhost:4200/vendor.bundle.js:72621:18)
    at CompiledTemplate.proxyViewClass.AppView.internalDetectChanges (http://localhost:4200/vendor.bundle.js:72408:18)
    at CompiledTemplate.proxyViewClass.View_RecipeListComponent0.detectChangesInternal (/AppModule/RecipeListComponent/component.ngfactory.js:96:20)
    at CompiledTemplate.proxyViewClass.AppView.detectChanges (http://localhost:4200/vendor.bundle.js:72423:14)
    at CompiledTemplate.proxyViewClass.DebugAppView.detectChanges (http://localhost:4200/vendor.bundle.js:72618:44)
    at CompiledTemplate.proxyViewClass.AppView.internalDetectChanges (http://localhost:4200/vendor.bundle.js:72408:18)
    at CompiledTemplate.proxyViewClass.View_RecipesComponent0.detectChangesInternal (/AppModule/RecipesComponent/component.ngfactory.js:83:19)
    at CompiledTemplate.proxyViewClass.AppView.detectChanges (http://localhost:4200/vendor.bundle.js:72423:14)
    at CompiledTemplate.proxyViewClass.DebugAppView.detectChanges (http://localhost:4200/vendor.bundle.js:72618:44)
    at CompiledTemplate.proxyViewClass.AppView.internalDetectChanges (http://localhost:4200/vendor.bundle.js:72408:18)

Here is my angular version:

angular-cli: 1.0.0-beta.28.3
node: 7.6.0
os: win32 x64
@angular/common: 2.4.9
@angular/compiler: 2.4.9
@angular/core: 2.4.9
@angular/forms: 2.4.9
@angular/http: 2.4.9
@angular/platform-browser: 2.4.9
@angular/platform-browser-dynamic: 2.4.9
@angular/router: 3.4.9
@angular/compiler-cli: 2.4.9

Thanks for any suggest.

Added information:

Recipe class object:

export class Recipe {
    constructor(public name: string, public description: string, public imagePath: string) {

    }
}

Upvotes: 1

Views: 1696

Answers (2)

J. Adam Connor
J. Adam Connor

Reputation: 1734

The first thing that jumps out at me is that you don't actually bind to recipe in your template. You are attempting to bind to its properties by themselves. Try {{recipe.name}}, for example, instead of just {{name}}.

There is another error here:

<app-recipe-item> [recipe]="recipe" (click)="onSelected(recipe)"></app-recipe-item>

Notice the closed tag at the app-recipe-item selector. I don't know if that's present in your markup, or not. Fix this like this.

 <app-recipe-item [recipe]="recipe" (click)="onSelected(recipe)"></app-recipe-item>

Finally, can you explain why you'd emit recipe on clicking app-recipe-item when you already have recipe in the parent component? In other words, app-recipe-item appears to be getting recipe from the parent component. It's unclear why the parent component would need to get it back from the child.

Upvotes: 1

dimeros
dimeros

Reputation: 101

Try default initialization of: @Input() recipe: Recipe = new Recipe() using a 'default' object inside the RecipeItemComponent or/and define the public recipe: Recipe inside the app-recipe-list with a default Recipe object.

Upvotes: 0

Related Questions