SuperMarco
SuperMarco

Reputation: 721

Emberjs - modifying array

I have some issue with Ember that I don't really understand. I have an array like this :

var device.images = [
    0: {
        url: "url",
        key: "key"
    },
    1: "url2",
    2: "url3",
    3: "url4"
];'

And in my controller, inside a map I try to modify every item from the array doing this :

device.images[idx] = image;

image is a new object that look like the first item of my array. But I always get the assertion failed :

Assertion Failed: You must use Ember.set() to access this property (of [object Object]...

How can I fix that ? because that should normally works no ?

[edit] Here is the complete code :

loadGallery: function( device ) {

        var that = this;
        var images = device.images.map( function( item, idx ) {
            return new Ember.RSVP.Promise(function( resolve ) {
                if ( item.url ) {
                    resolve( item );
                }
                else {
                    resolve( that.imageStore.readImage( that, item ) );
                }
            })
            .then( function( image ) {
                device.images.set( idx, image );
                that.set( 'selectedItem.images', device.images );
                return image;
            });
        });
        return Ember.RSVP.Promise.all( images );
    },

Upvotes: 0

Views: 386

Answers (1)

panta82
panta82

Reputation: 2721

[Edit: first attempt was wrong]

It seems you should be able to use item[index] = value construct. Example usage:

App.IndexRoute = Ember.Route.extend({
  resolveImage: function (that, item) {
    return {
      url: item,
      key: "resolved"
    };
  },
  model: function() {
    var device = {
      images: [
        {url: "a", key: "existing"},
        "b",
        "c"
      ]
    };
    var that = this;
    var images = device.images.map(function(item, idx) {
      return new Ember.RSVP.Promise(function(resolve) {
        if (item.url) {
          resolve(item);
        }
        else {
          resolve(that.resolveImage(that, item));
        }
      })
      .then(function(image) {
        device.images[idx] = image;
        return image;
      });
    });
    return Ember.RSVP.hash({
      model: Ember.RSVP.Promise.all(images),
      device: device
    });
  },
  setupController: function (c, m) {
    c.set("model", m.model);
    c.set("device", m.device);
  }
});
  <script type="text/x-handlebars" data-template-name="index">
  <h2>From model</h2>
  <ul>
    {{#each item in model}}
      <li>{{item.url}} - {{item.key}}</li>
    {{/each}}
  </ul>
  <h2>From device</h2>
  <ul>
    {{#each item in device.images}}
      <li>{{item.url}} - {{item.key}}</li>
    {{/each}}
  </ul>
  </script>

JSBin here.

Barring some bug elsewhere in your code, the only remaining solution is that you are using Ember.Data and images isn't really an array but a custom class that merely implements one or several of Ember's array/enumerable mixins. [...] construct is a syntactic sugar that is hardcoded into javascript and not available to library authors to override.

I can't help you there much, as I don't use Ember.Data. You can try using explicit array mutation methods from Ember.MutableArray interface. Eg:

device.images.replace(idx, 1, [image]);

Alternatively, use object.set(key, value) construct (my first suggestion), with caveat that key value must be a string. Eg:

device.images.set(String(idx), image);

If neither of these work, you can just try to build up a new array instead of replacing members of the existing one.

Upvotes: 1

Related Questions