5

First off I am new to Typescript and Angular 2 and this seems like an obvious answer but I can't seem to get it to work. I have the following model

export interface IBrand {
    brandID: number;
    name: string;
    image: string;
}

Then I have the component class

import { Component, OnInit }  from '@angular/core';
import { Router, RouteParams } from '@angular/router-deprecated'
import { bootstrap } from '@angular/platform-browser-dynamic';

import { IBrand } from './brand';
import { BrandService } from './brand.service';

@Component({
    selector: 'data-bind',
    templateUrl: 'app/dashboardApp/brands/brand-list.component.html',
    styleUrls: ['app/dashboardApp/brands/brand-list.component.css']
})

export class BrandListComponent implements OnInit {
    brands: IBrand[];
    errorMessage: string;
    newBrand: IBrand;
    pageTitle: string = 'Brands';

    constructor(private _brandService: BrandService,
        private _router: Router) {
    }

    ngOnInit(): void {
        this._brandService.getBrands()
            .subscribe(
            brands => this.brands = brands,
            error => this.errorMessage = <any>error);
    }    
}

And then I have the following html

<div class="form-group">
    <label for="brandName">Brand:</label>
    <input type="text" class="form-control" placeholder="Name" id="brandName" [(ngModel)]="newBrand.name" />
</div>

I can't get the properties of IBrand to work successfully and I get the error

platform-browser.umd.js:962 ORIGINAL EXCEPTION: TypeError: Cannot read property 'name' of undefined

However I can bind it easily to something like pageTitle. Any ideas that can point me in the right direction?

5 Answers 5

9

It's been a while since I have asked this question, and it's starting to get some views so I will add my answer.

First I would need to change my interface to a class and add a constructor.

export class Brand {
  constructor() {}
  brandID: number;
  name: string;
  image: string;
}

Now that I have a constructor I can use the new operator to instantiate the object.

export class BrandListComponent implements OnInit {
  brands: Brand[];
  errorMessage: string;
  newBrand: Brand = new Brand();
  pageTitle: string = 'Brands';

  (...)
}

Now I have the desired brand initialized without any data and I can bind it to the model. Hope this helps.

Sign up to request clarification or add additional context in comments.

2 Comments

thanks a lot, I don't know why but when I follow angular docs angular.io/guide/forms#create-the-hero-model-class it has defined the fields inside constructor, and I get error of cannot read property of undefined.. but when I follow your answer (moving fields outside contructor) I don't get any errror
That's because they are trying to create a class with values. In a lot of CRUD situations you want to be able to create an instance of the class with no values. If you added ? after each property name allowing them to be null or you could pass in a value. Then the angular docs version would work. Just depends on your needs.
6

You could follow this approach if you don't want to use class.

export interface IBrand {
brandID: number;
name: string;
image: string;
}

And now you could create empty objects for typed variables like this.

brand: IBrand = {} as IBrand;

Avoid using classes if you just want to use it for type safety instead use interface as best practice to make your bundle size smaller.

Comments

1

I think that you need to initialize your newBrand property as described below:

export class BrandListComponent implements OnInit {
  brands: IBrand[];
  errorMessage: string;
  newBrand: IBrand = {}; // <-----
  pageTitle: string = 'Brands';

  (...)
}

In your case, this property is never initialized and you have the error:

Cannot read property 'name' of undefined

1 Comment

Thanks! I get a typescript error now saying that "Type '{}' is not assignable to type 'IBrand'. Property 'brandID' is missing in type '{}'. Is that something I can ignore or do I need to instantiate the properties?
0

You probably found out already, but you can/should use: newBrand: IBrand = {}; if your interface properties are optional:

export interface IBrand {
    brandID?: number;
    name?: string;
    image?: string;
}

Comments

-1

You have to write a class for types. Not Interfaces.

newBrand: Brand = new Brand();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.