johnwj
johnwj

Reputation: 449

How to return Ajax data inside Ember computed property

I'm trying to return data from an Ajax call in a computed property. I understand because of the asynchronous nature, I can't do the following. However, I can't return a promise because I need to return the data in a particular format of an array with objects with a property and label.

options: Ember.computed('name', function() {
    let id = name.id;
    const url = '/testUrl/id=' + id;
    let optionArray = [];
    Ember.$.ajax({
      url: url,
      type: 'GET',
    }).then((response) => {
      let arr = JSON.parse(response);
      for (let idx = 0; idx < arr.length; idx++) {
        optionArray.addObject({
          property: idx,
          label: arr[idx]
        });
      }
      return optionArray;
    });
  })

How do I return the data from the Ajax call in the format specified above?

Upvotes: 0

Views: 841

Answers (2)

zureka
zureka

Reputation: 66

You could always initiate the AJAX request within the init method of your component/controller. It is typically best practice to load data on the model from the route, but there are occasionally instances where this sort of pattern tends to make things easier:

init() {
    this._super(...arguments);
    this.options = {};
    this.getAndSetOptions();
},

getAndSetOptions() {
    /* Make AJAX request and modify result as needed */
    Ember.set(this, 'options' result);
}

Also, to handle asynchronous behavior (promises, callbacks, etc.) in your Ember app I would suggest checking out Ember Concurrency.

Upvotes: 0

Chhirag Kataria
Chhirag Kataria

Reputation: 288

In general, it is a bad practice to have ajax calls in a computed property -- try having it in your model in the route, and pass the data down to your component (or wherever you are using your options property). I see you are observing 'name' -- is there a reason you are doing that? Since the url seems to be the same no matter the name, it seems like you don't need the computed property at all. That said, a computed property always needs to return something. So the only way I can think of making this work would be to return the promise in the computed property and then use it somewhere else in your code - maybe another function, wait for it to resolve in there and then set the optionArray.

To reiterate, I feel like you should ask yourself if you really need this logic in a computed property or if you can do it in a route. If not a route, at least in a function or another hook. If you provide more context, I can maybe help you better.

Upvotes: 3

Related Questions