Suren Konathala
Suren Konathala

Reputation: 3597

Emberjs - How to map api json response to a model?

While trying to build an Ember.js sample application, to call a REST Api and display results. I was able to call, fetch and display the results. In the component I am reading through the json response results.

How can I map the response data to a pre-defined model and use that in the component instead? I could not find relevant docs at https://guides.emberjs.com/release/models/defining-models/ or https://guides.emberjs.com/release/in-depth-topics/making-api-requests/#toc_where-to-make-api-requests

Code details:

  1. Using this sample API https://reqres.in/api/users
  2. Model: (--update--)
export default class UserModel extends Model {
  @attr('string') id;
  @attr('string') firstname;
  @attr('string') lastname;
  @attr('string') email;
  @attr('string') avatar;
}
  1. Route:
export default class UsersRoute extends Route {
  async model() {
    let response = await fetch('https://reqres.in/api/users');
    let data = await response.json();
    return data.data;
  }
}
  1. Template:
<UserList
  @title="List of Users"
  @users={{@model}}
/>
  1. Component:
{{#each @users as |user|}}
    <tr>
      <td>{{user.id}}</td>
       <td>{{user.first_name}}</td>
       <td>{{user.last_name}}</td>
       <td>{{user.email}}</td>
    </tr>
  {{/each}}

Upvotes: 0

Views: 838

Answers (1)

Charles Fries
Charles Fries

Reputation: 365

Generate a user model:

ember g model user

import Model, { attr } from '@ember-data/model';

export default class UserModel extends Model {
  @attr('string') email;
  @attr('string') firstName;
  @attr('string') lastName;
  @attr('string') avatar;
}

Generate an application adapter and serializer:

ember g adapter application
ember g serializer application

Add your API URL to the adapter:

import JSONAPIAdapter from '@ember-data/adapter/json-api';

export default class ApplicationAdapter extends JSONAPIAdapter {
  host = 'https://reqres.in/api'; // the `users` part of the path is autogenerated based on the model name
}

Update the serializer:

import JSONSerializer from '@ember-data/serializer/json'; // note that this is not the default serializer, JSONAPISerializer
import { underscore } from '@ember/string';

export default class ApplicationSerializer extends JSONSerializer {
  // specify underscore-formatted keys
  keyForAttribute(attr) {
    return underscore(attr);
  }

  // use the `data` property in the payload as the serializable response
  normalizeResponse(store, primaryModelClass, payload, id, requestType) {
    payload = payload.data;
    return super.normalizeResponse(store, primaryModelClass, payload, id, requestType);
  }
}

Update your route to use Ember Data methods instead of raw fetch:

import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';

export default class UsersRoute extends Route {
  @service store;

  model() {
    return this.store.findAll('user');
  }
}

And finally you can then use the data (using camelcase-formatted attributes):

{{#each @users as |user|}}
  <tr>
    <td>{{user.id}}</td>
    <td>{{user.firstName}}</td>
    <td>{{user.lastName}}</td>
    <td>{{user.email}}</td>
  </tr>
{{/each}}

Upvotes: 2

Related Questions