Search code examples
ember.jsember-dataember-cli

How do I display grouped results in an EmberJS Application


I've created a simple EmberJS application that lists jobs from a headless CMS. The jobs data from the backend is in this format

[
   {
      "id": "1234",
      "description": "Test description"
      "category": "Human Resources"
   },
   {
      "id": "4321",
      "description": "Test description"
      "category": "Human Resources"
   },
   {
      "id": "5678",
      "description": "Test description"
      "category": "Information Technology"
   }
]

My app displays the results in the order that they're returned as expected but I'd like to group the results by category so that the results are displayed like this:

Human Resources

  • 1234
  • 4321

Information Technology

  • 5678

Thanks in advance for any help.

Note: I'm using EmberJS version 3.19

EDIT

My current model is just the job model

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

export default class JobModel extends Model {
  @attr Title;
  @attr Description;
  @attr Type;
  @attr Slug;
  @attr category;
  @attr job_type;
  @attr region;
  @attr company;
  @attr createdAt;
}

I load the data using ember-data in my index route (home page) like this

export default class IndexRoute extends Route {
  @service store;
  async model() {
    return this.store.findAll("job");
  }
}

With that setup, I can iterate through the jobs and display them in a list on my home page like this:

{{#each @model as |job|}}
        <Job @job={{job}} />
{{/each}}

Not sure if it is possible but I want to be able to display each category and the jobs included in that category with a structure like the below pseudocode:

{{#each category}}
<h3>{{category.name}}</h3>
  {{#each job-in-category}}
        <Job @job={{job}} />
  {{/each}}
{{/each}}

Solution

  • Basically you could either add the logic to your routes model hook or create a Controller and use a getter.

    In the route you could do

      async model() {
        const jobs = await this.store.findAll("job");
        return jobs.reduce((groups, job) => {
          if(!groups.has(job.category)) {
            groups.set(job.category, []);
          }
          groups.get(job.category).push(job);
          return groups;
        }, new Map());
      }
    

    and use it in your template:

    {{#each-in @model as |category jobs|}}
      <h3>{{category}}</h3>
      {{#each jobs as |job|}}
        <Job @job={{job}} />
      {{/each}}
    {{/each-in}}
    

    you could produce the same structure in a getter on the controller or use a dedicated component for it. Also maybe you want to create a dedicated ember-data model for your category and use a relationship.