Reformatting model data in controller

Thanks! I like working examples over code snippets but I agree that can be confusing. Perhaps I need to work on some doc to explain more.

1 Like

I think I figured it out. You have an Ember Data model that is an array-like object. You want to iterate over it with forEach, map, or other array functions. This is how:

this.get('model').toArray().forEach(function(item) {
    console.log(item.get('text'));
});
3 Likes

So I know I could to this int eh afterModel function in the routes, but what I was concerned about is that I really need the same data I retrieve from the API formatted in 2 different ways. One for a specific component that I am using and another for other parts of the template.

All of the examples in the routes seemed to assume that I only ever want the data formatted a single way for all possible views.

That worked. The key must have been the .toArray call against the model that was returned from ember-data in my route.

@emberigniter. This is a great example of the topic in the other thread. We finally got to the right (or at least a working answer) but it was no where near as simple as it should have been for what to me seems like a fairly common use-case.

1 Like

So if you want to keep the model, and have a different data structure based on it, and using @Gaurav0’s answer, you need something like:

mapData: Ember.computed('model', function() {
 return this.get('model').toArray().reduce(function(acc, item) {
   // do you data transform
 });
})

Which you can then use in a template like:

{{#each mapData as |point| }} ... {{/each}}

Note that mapData refers to a method in the controller. If this was a component it would be identical.

Does that help?

I’m happy that worked for you.

I asked you to post the content of this.get('model') because I’m very curious.

If you were retrieving data via this.store (Ember Data), the array-model it returns has a TON of functions to iterate. Granted, it’s not a plain-old Javascript array, but it can do forEach, filter, map, reduce, plus other goodies such as mapBy.

I actually don’t understand why you needed toArray().

1 Like

I am getting the model populated in my routes via this.store.

I will post the output of console.log(this.get(‘model’)) later tonight and see if that helps. If the .toArray isn’t needed then I would love to simplify the code.

Forgive the typing, sent from my iPhone

@jesmith I think I understand where the confusion is.

It seems that you want to have two different “views” of the data available. If that’s the case you should probably just create a computed property in your controller. Take a look at the docs for Enumerables and here for the methods available. I would suggest using map like so:

export default Ember.Controller.extend({

  mapData: Ember.computed("model", function() {
    let model = this.get("model");

    return model.map(function(item) {
      // item is the nth element in your data
      return {title: item.title, lat: item.latitude, lng: item.longitude};
    }, model);
  })
}); 

Then just refer to mapData in your template.

I’m assuming that title is already a property in your data. If you need to do anything fancier you can pass in the index and a ref to the original enumerable (model) as 2nd & 3rd params to the callback. You can also pass in this as 3rd param to map.

yes, but that doesn’t account for model being a collection of items returned via ember data (which is what I have.)

The problem was always figuring out how to best iterate over the collection as part of creating the computed property. Many suggestions have been made about how to do the computed property but most have ignored the iteration part (which has to come first as otherwise the rest doesn’t matter).

But yes, i want 2 different “views” of the data as my template natively uses one, and a component that I am using as a dependency requires the data formatted a different way.

I have it working now, it’s just a question of whether or not the .toArray call is actually necessary.

It looks like @brian_ally’s suggestion and mine are exactly the same.

“How to best iterate”, “the iteration part”… aren’t those synonyms for “transforming a data structure”? Nothing Ember-specific, is it? I mean, that’s a separate Javascript issue. As long as you have forEach, map, etc, which the original model and its derived (computed) property both have.

@jesmith The dataMap array shouldn’t need to be an Ember-Data object because it’s computed from the ED object. Just don’t make any updates directly to mapData. It’ll update itself as model changes.

whoops! I think that should be:

mapData: Ember.computed("model.[]", function() {

They should be, but multiple tests of various permutations weren’t working the iteration part so that I could do the individual transformations.

And my working code still doesn’t use map or reduce, etc.

This still feels like a case where their is some magic component to how this is supposed to be setup that I just don’t see and the docs don’t explain.

I had tried this.get('model).forEach and that gave me no output at all as the forEach seemed to think the return from the model wasn’t an array. While I am new to Ember I am not new to JavaScript or programming. I get array iteration patterns and none of them worked until we explicitly added the toArray call which seems very unintuitive.

But it’s frustrating when a question is asked and the example responses omit part of the problem. It’s like solving the second step of a puzzle but not the first.

Forgive the typing, sent from my iPhone