6

I want to use [(ngModel)] for a nested object, but is giving me an error

Cannot read property 'mxn' of undefined

these are the data structure of my models:

company.model.ts

import Currency from './currency.model';

class Company {
_id: string;
name: string;
maxLimit: number;
source: [string];
deliveryMethod: [string];
currency: Currency;
date: Date;

constructor() {
    this.name = '';
    this.date = new Date();
    this.maxLimit = 0;
    this.source = [''];
    this.deliveryMethod = [''];
    this.currency.mxn = 0;
    this.currency.php = 0;
    }
}

export default Company;

currency.model.ts

class Currency {
mxn: number;
php: number;


constructor() {
    this.mxn = 0;
    this.php = 0;
}
}

export default Currency;

and this is part of company.ts

public newCompany: Company = new Company();
companiesList: Company[];
editcompanies: Company[] = [];

and HTML

in HTML page I'm able to show the mxn value by just using :

<tr class="companies" *ngFor="let company of companiesList">
{{company.currency.mxn}}

but when I want to use it with ngModel two-way binding for updating the value and sending it to the database it doesn't work.

[(ngModel)] = "newCompany.currency.mxn" it produces the mentioned error above. if I use [(ngModel)] = "newCompany.currency" it doesn't give me an error but the code it's useless since i can't assign any value to mxn.

I have to say that [(ngModel)] = "newCompany.name" it works fine with this and I can update the name.

the backend works fine as I tried it with Postman. the problem is angular side.

so the question is if my data structure is correct how can I use two-way binding for the nested object?

Milad
  • 95
  • 1
  • 10

3 Answers3

3
currency: Currency;
...
constructor() {
  ...
  this.currency.mxn = 0;
  this.currency.php = 0;
}

mxn and php do not exist yet until you instantiate an instance of Currency. The instance currency is null. It doesn't contain any properties.

currency: Currency;
...
constructor() {
  ...
  this.currency = new Currency(); // invoke Currency constructor, create mxn and php with value 0, therefore you dont need this.currency.mxn = 0 and same to php
}
Haifeng Zhang
  • 24,348
  • 16
  • 55
  • 104
2

A slight change in your Company model should be enough:

class Company {
  _id: string;
  name: string;
  maxLimit: number;
  source: [string];
  deliveryMethod: [string];
  currency: Currency = new Currency(); // provide an instance, otherwise this field will be undefined
  date: Date;

  constructor() {
      this.name = '';
      this.date = new Date();
      this.maxLimit = 0;
      this.source = [''];
      this.deliveryMethod = [''];
      this.currency.mxn = 0;
      this.currency.php = 0;
      }
  }

export default Company;
Armen Vardanyan
  • 2,661
  • 1
  • 12
  • 29
2

It looks like you're not instantiating the currency field in your constructor. Try by changing the

currency: Currency;

to

currency = new Currency();

It's probably working with your companiesList because probably (I'm guessing here) your backend instantiate them for you. And when you instantiate the newCompany which I assume you do by yourself it's not working cause of the missing new Currency()

SebOlens
  • 489
  • 3
  • 13