Why don't models fire property change hooks?


#1

Please see https://ember-twiddle.com/26abcff088d4ff581b230cab7df178e2?openFiles=models.test.js%2C

When I type into the input fields, the model properties are being modified and the dirtyType on the model is being changed to updated. However, neither set, propertyWillChange or propertyDidChange are (as far as I can tell) being fired on the model.

Either: a) I’m not really overriding those functions like I think I am b) I don’t understand what those hooks do c) Something’s wonky

I’m really looking for a way to write an observer/CP that says field X was modified anytime any model property changes.

This is of course a means to an end… what I’m really trying to do is have a dirty track on the model that effectively ignores certain attrs (so in my twiddle, maybe I only care if lastname is changed for example) but without specifically setting a CP on every single field.


#2

These are not hooks, they are methods you can call. You should not override them. Have a look at the api docs for them to see what they are for


#3

I understand their normal use-case but since Model.changedAttributes() is a method and not a property that I can use as a dependency for a CP, I was looking for another way to intercept changes being propagated to the model from the UI. I’m still confused why changes I type into the UI don’t appear to call any of those functions. To me, this is the underlying issue that’s bothering me…how is the input helper updating the underlying model and obviously alerting watchers to that fact without calling these methods?

Model provides ‘dirtyType’ which is great for the normal use-case of “is this model dirty” but not in my case since I only want to know if anything but a couple of attributes have changed. I believe you and I originally spoke on Slack and you pointed me toward a buffered proxy addon but since that also relied on set being called to do it’s thing, it wasn’t doing what I wanted it to either (or I’m too dense to understand how to get it to do what I want) because as I believe I’ve demonstrated, it’s not calling set.


#4

@robertneville73 Do you have more details on what you are trying to accomplish in the grand scheme of things? https://github.com/DockYard/ember-changeset does something similar to what you are describing but I may be totally off :wink:


#5

@acorncom It’s pretty basic. For example: I’ve got a template showing 20-30 input helpers bound to a model’s properties. I want to enable/disable the “Save” button let’s say based on the state of the model (dirty / not dirty), however with one wrinkle. There are 2 attributes on that model I need to ignore changes on for purposes of determining if it’s really dirty or not.

So my problem is this…one of the attributes I don’t care about has changed so model.dirtyType reports that it’s changed. I can of course call model.changedAttributes() and inspect the result to see if the changes are one’s I care about or not, but then I have to know to call that. Once the dirtyType has flipped to “changed”, I have nothing to key off of to alter the UI with.

My thinking was, if I could intercept changes happening to the model (all of them) then I could maintain my own dirty flag by inspecting model.changedAttributes() whenever something changed. By changed, I mean that I’ve typed something into one of the input helpers for an attribute that I care about. The trouble I’m having is that it does not seem that set is called on the model when this happens. So I looked for other ways I could intercept, on the model an effective “heySomethingChangedWithMe” event that would include changes made to the model via the UI.


#6

So it sounds like you are doing two-way binding for all your attributes, correct? Could you shift your two “should not be altered” attributes to use one way bindings instead? You’d be able to watch the changes that way (and then propagate the changes through to the model if needed) without getting into observers …


#7

Long story as to why, but no, not in this case though for the generalized example I gave that would work. Even so, it seems like there’s something missing that should allow me to do this in a less hacky way.