Parsing a json object in a route


#1

ember-cli: 2.13.2 node: 7.8.0

Hello, I’m a newbie at ember and I want to do something that looks super simple, but I can’t find the right way.

I have this code in ./routes/tutoriel-01.js

import Ember from 'ember';                              
import DS from 'ember-data';                            
import config from '../config/environment';             
const {Logger}= Ember;                                  
                                                        
export default Ember.Route.extend({                     
  model: function() {                                   
    return Ember.$.getJSON(config.APP.drupal_tutoriel); 
  }                                                     
}); 

And the following in ./templates/tutoriel-01.hbs

 <ul>                             
  {{#each model as |elem|}}      
    <li>{{elem.node_title}}</li> 
  {{/each}}                      
</ul>                            

The problem is that $.getJSON return 8 objects and I just want one. So the template will print all the node_title of the 8 objects.

[
  {
    "node_title": "Événements",
    "nid": "1234",
    "numero_tutoriel": "1",
    "field_image_tutoriel": "http://example.org/sites/files/evenements_tuto_mobile.png",
    "body": "<p>some text</p>\n"
  },
  {
    "node_title": "À lire",
    "nid": "45678",
    "numero_tutoriel": "2",
    "field_image_tutoriel": "http://example.org/sites/files/tuto_mobile.png",
    "body": "<p>more text.</p>\n"
  },
(...)
]

I though that I could use in my route something like:

return Ember.$.getJSON(config.APP.drupal_tutoriel)[0] 
return Ember.$.getJSON(config.APP.drupal_tutoriel).[0]

or

in my template:

{{#each model.[0] as |elem|}}

but it’s not working.

Once I have working code, I’ll try it with a promise.

I read about Ember Data, but I can figure out how to use it this particular case.

TIA

-Emmanuel


#2

Hello,

Is your object an Ember Model? If it’s not, once I had a problem with custom objects as well and requests/parses that I was able to solve using EmberObject:

const MyObject = Ember.Object.extend({
  // empty object
});

var result = [];
$.ajax({
  type: "GET",
  url: 'host'

}).then(function (response) {
  
  response.itemName.forEach(function (item) {
    var model = MyObject.create(item);
    result.addObject(model);

  });
 
}, function (error) {
 // some code
});

Maybe you can access only the items you want doing something like this.

Hope it helps.


#3

Hi Emmanuel!

It does not work because Ember.$.getJSON returns a promise, so you are trying to get the property 0 of the Promise object. You need to use .then, like so:

export default Ember.Route.extend({                     
  model: function() {                                   
    return Ember.$.getJSON(config.APP.drupal_tutoriel)
      .then(resolved => resolved[0]); 
  }                                                     
});

I do warn that since it’ll be the individual object, you won’t be able to use it with the {{each.


#4

Thanks for the answer amandaBrito and locks.

lock, if I use a promise, will I be able to modify/create a new object that will contain only the object I’m looking for so to be able to use {{each in my template?

In the end, I really want to use a promise because it make more sense because you can more easily catch problems.

TIA


#5

If you just want to operate on the first one, as indicated by @locks you can use:

.then(resolved => resolved[0]);

In this case, your model will contain just the first element, so you can do:

<li>{{model.node_title}}</li>

If you want to use the .hbs you had, you could use:

.then(resolved => [ resolved[0]) ];

There doesn’t seem to be much point to building an array around one element if the one element is all you want, but maybe you’re doing something more later?

If your goal was to get the whole thing, but just consume the first element in this particular page, that’s a different kettle of fish. You could a computed property on the js side of your page to do it - perhaps overkill - or you could perhaps use a {{get}} helper in some clever way. If you’re using the truth helpers, the following would work - perhaps not elegant, though:

{{#each model as |elem index|}}
    {{#if (eq index 0)}}
    <li>{{elem.node_title}}</li> 
    {{/if}}
  {{/each}}                      

Hopefully someone else has a better suggestion.

Cheers…


#6

Thanks Lupestro for the answer. Especially for the handlebars code.

In the end, the problem somehow resolved itself since I’m using a slider and I need all objects. (see ember-cli-swiper https://suven.github.io/ember-cli-swiper/ for the slider)

And in the template, I can somehow refer to each individual object with

model.[INDEX].PROPERTY

So, this is my code now and it works well:

./routes/tutoriel.js

import Ember from 'ember';
import config from '../config/environment';

export default Ember.Route.extend({
  model: function() {
    let tutoriel = Ember.$.getJSON(config.APP.drupal_tutoriel)
      .fail(function( jqxhr, textStatus, error ) {
        var err = textStatus + ", " + error;
        console.log( "Échec de la requête: " + err );
      });
    return tutoriel;
  }
});

./templates/tutoriel.hbs

{{#swiper-container pagination=true loop=false}}
  {{#swiper-slide class='myslide myslide-1'}}
    <figure class="tutoriel-img"><img src="{{model.[0].field_image_tutoriel}}" alt="image tutoriel" /></figure>
    <header class='tutoriel'>
        <h2>{{model.[0].node_title}}</h2>
        <p class='tutoriel'>{{{model.[0].body}}}</p>
    </header>
  {{/swiper-slide}}
  {{#swiper-slide class='myslide myslide-2'}}
    <figure class="tutoriel-img"><img src="{{model.[1].field_image_tutoriel}}" alt="image tutoriel" /></figure>
    <header class='tutoriel'>
        <h2>{{model.[1].node_title}}</h2>
        <p class='tutoriel'>{{{model.[1].body}}}</p>
    </header>
  {{/swiper-slide}}
(...)
{{/swiper-container}}

I’m still struggling a little bit to make head around the way jQuery and Ember handle promises, but I guess, I’ll get there.

Thanks!