drbishop drbishop - 1 month ago 8
Javascript Question

Two-way binding nested objects

I have the following class in my Angular2 app:

export class MyClass {
name: Object;
}


The name object has a dynamic property to load the current language. Currently, when I want to do two-way binding, I'm doing like this:

item: MyClass = {
name: { en: string }
}


That way, in my HTML, I just use
[(ngModel)]="item.name.en"
. However, I have many other properties in that class as well.

Do I have to define all of them inside
item
? If I try to call only
MyClass
(
item: MyClass;
), I get
undefined error
.

Is there a better way to do that?

Answer

A few things:

(1) Avoid using Object as a type, as noted in the docs:

The any type is a powerful way to work with existing JavaScript, allowing you to gradually opt-in and opt-out of type-checking during compilation.
You might expect Object to play a similar role, as it does in other languages. But variables of type Object only allow you to assign any value to them - you can’t call arbitrary methods on them, even ones that actually exist

So it's better to go with any:

export class MyClass {
    name: any;
}

But then you lose the type safety feature the typescript is giving you (same if you use Object), why not:

export class MyClass {
    name: { [language: string]: string };
}

(2) Doing this:

item: MyClass = {
    name: { en: string }
}

Is problematic in that it does not create a new instance of MyClass, it only creates an object with the same properties (the reason that it compiles with no errors is because "typescript is based on structural subtyping").

If you want to create an instance then:

item = Object.assign(new MyClass(), {
    name: { en: string }
});

Or you can create a constructor which populates the data:

export class MyClass {
    name: { [language: string]: string };

    copnstructor(name: { [language: string]: string }) {
        this.name = name;
    }
}

item = new MyClass({
    name: { en: string }
});