2

I can't bind my Angular HTML to my devices array because there is a mismatch between what I am expecting the object to look like. I want to bind to device.modelName but it fails because the object I'm actually getting back has the property ModelName without camelCase!

Googling a solution I saw that I should use type assertion so I did by adding <DeviceStatus[]> resulting in the line <DeviceStatus[]>response.json()); in my component class. Unfortunately this didn't seem to change anything.

Why does it seem like my json object isn't being mapped properly?

My model interface:

export interface DeviceStatus {
    deviceId: string;
    modelName: string;
}

My component:

export class FetchDataComponent {
    public devices: Observable<DeviceStatus[]>;

    constructor(http: Http) {
        this.devices =
            http.get('api/Devices')
                .map((response: Response) => <DeviceStatus[]>response.json());

        this.devices.subscribe(x => console.log(x));
    }
}

The result in Chrome console:

(2) [Object, Object]
  0: Object
    DeviceId: "1"
    ModelName: "Model Name"
...
Nitzan Tomer
  • 155,636
  • 47
  • 315
  • 299
Kyle V.
  • 4,752
  • 9
  • 47
  • 81
  • 1
    AFAIK, since JavaScript/TypeScript are case sensitive, it won't match "modelName" with "ModelName". When I've run into this before, I fixed it on the server side. I was using ASP.NET at the time and found a JSON Formatter that I could use in my Web API Service that changed the output to camel casing. – DeborahK Jun 28 '17 at 16:34
  • @DeborahK that would be great if I could get my hands on that JSON Formatter. I'm also using ASP.NET on the server. – Kyle V. Jun 28 '17 at 16:45

2 Answers2

3

Type assertion only informs the compiler, it does nothing to the actual data as it says in the docs:

A type assertion is like a type cast in other languages, but performs no special checking or restructuring of data

Always remember that the type system in typescript doesn't get translated to javascript, so in runtime you don't have that.

You'll need to do the convertion yourself:

this.devices =
    http.get('api/Devices')
        .map((response: Response) => response.json().map(device => ({
             deviceId: device.DeviceId,
             modelName: device.ModelName
        }));
Nitzan Tomer
  • 155,636
  • 47
  • 315
  • 299
  • Chose this as the accepted answer since my original question mentioned type assertion explicitly and did not specify ASP.NET. Anyone finding this who *is* using ASP.NET though, @DeborahK provided an excellent solution. – Kyle V. Jun 28 '17 at 16:55
1

Here is the ASP.NET code using the formatter:

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver=
  new CamelCasePropertyNamesContractResolver();

It converts the properties to camel case before returning them in the response.

You can find out more about it here: http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Serialization_CamelCasePropertyNamesContractResolver.htm

And there is a more complete example in this post here: Web API 2: how to return JSON with camelCased property names, on objects and their sub-objects

DeborahK
  • 57,520
  • 12
  • 104
  • 129