Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type array does not seem to observe changes correctly #81

Open
st-h opened this issue Oct 3, 2015 · 9 comments
Open

type array does not seem to observe changes correctly #81

st-h opened this issue Oct 3, 2015 · 9 comments

Comments

@st-h
Copy link
Contributor

st-h commented Oct 3, 2015

To me it seems that when an element is added or removed from an array, which is mapped via 'type: "array"', these changes are not observed as they should be. Probably it would be a good idea to use something like embers ArrayProxy internally, so we could observe changes to arrays more effectively?

gordonkristan added a commit that referenced this issue Oct 10, 2015
gordonkristan added a commit that referenced this issue Oct 10, 2015
gordonkristan added a commit that referenced this issue Oct 10, 2015
@gordonkristan
Copy link
Contributor

I just added a test here and it seems like changes are being observed correctly. Is this an issue that you can reproduce?

@st-h
Copy link
Contributor Author

st-h commented Oct 11, 2015

I think the test shows exactly what I am perceiving as an issue

the change to the array does not trigger any observers:
ticket.get('numbers').pushObject(0);

However invoking the setter on the parent, does trigger an observer:
ticket.set('numbers', ticket.get('numbers').slice(0, 6));

To me it seems that this could be prevented by using something like embers ArrayProxy which would observe any change to the array itself.

@gordonkristan
Copy link
Contributor

the change to the array does not trigger any observers:
ticket.get('numbers').pushObject(0);

It works just fine in that the test I wrote. Is there a situation where it isn't working for you?

To me it seems that this could be prevented by using something like embers ArrayProxy which would observe any change to the array itself.

Ember.Array has that functionality mixed in with Ember.MutableArray. Ember.ArrayProxy is only used when you want to keep the same object reference around but have the underly contents change (which isn't really our goal here).

@st-h
Copy link
Contributor Author

st-h commented Oct 14, 2015

Yes, it works IF you invoke the setter and set the array that is already there again. To me that is neither logical nor obvious. However, being there is a workaround which should not have any major impact (by invoking the setter), one could also keep the current behavior and make it more obvious by documenting it.

@gordonkristan
Copy link
Contributor

Yes, it works IF you invoke the setter and set the array that is already there again.

This is the part I'm not understanding. You don't have to invoke the setter. The following test passes. It never calls the setter but the observer is triggered.

test('Changes can be observed', 1, function() {
    var ticket = store.getRecord('lotteryTicket', '1');

    ticket.addObserver('numbers.[]', function() {
        ok(true);
    });

    ticket.get('numbers').pushObject(0);
});

@st-h
Copy link
Contributor Author

st-h commented Oct 16, 2015

Well, I am little baffled what is going on then.

I have a group model, which has a members property:

export default EG.Model.extend({
  members:  EG.attr({ type: 'array' })
});

In my route I am doing the following:

group.get('members').pushObject({'mail': 'some@mail.com', 'permission': 1});
group.save();

when I then debug into the changedAttributes() method of ember-graph, var client = this.get('clientAttributes.' + name); is always undefined for the members property. Therefore these changes never get serialized.

If I invoke the setter with the same array, everything works fine:

group.set('members', group.get('members').pushObject({'mail': 'some@mail.com', 'permission': 1}));
group.save();

@gordonkristan
Copy link
Contributor

I feel dumb. 😞 So observing these properties works just fine, the problem is that Ember Graph doesn't observe them. It's a fairly common use case but I haven't run into a solution yet (I need to look to see how Ember Data does it).

The technical issue is that I can't figure out how to have a model observe changes to objects that it holds as properties. Some scenarios are fairly easy to take care of. For instance, it's easy to see if an array had an item added or removed from it. But what if I have an array of objects and I change a property on that object? How will I observe that?

One solution I thought of (that I might try to implement), is to have custom attributes define their own observer keys. In your case, you might define a custom array attribute type and declare that the model should observe the members.@each.{mail,permisson} key.

Anyway, I understand your issue now, sorry it took so long. 😛 I'll take a stab at solving that this weekend and get back to you. 😄

@st-h
Copy link
Contributor Author

st-h commented Oct 17, 2015

No worries. There are some issues with the code I posted above as well 😄 ... I see where the problem is. I was under the impression that I read in the past that observing object changes within an array would be possible with the @each helper, but that does not seem to be the case. I came along this add on: https://www.npmjs.com/package/ember-cli-observe-all Probably it might be helpful

@gordonkristan
Copy link
Contributor

I made some headway on this over the weekend. I have it so that you can successfully watch the properties you need, but I'm having some issues with determining if a property is dirty or not. I think I may need to require custom property types to implement a clone() method or something similar. Either way, I'll keep you updated with the progress on this. This will also take me much closer to implementing embedded objects, so it's a win-win. 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants