0
votes

I have a model:

export default Model.extend({
  title: attr('string'),
  attributes: attr('jsonb')
});

Where attributes is a custom json filed stored as jsonb in Postgres.

let say:

{
"name":"Bob",
"city":""
}

So I can easily manipulate attributes using template
<form.element .. @property="attributes.city"/> or model.set('attributes.city','city name')

Problem: hasDirtyAttributes do not changing because technically we have old object. But when I try to copy object let say JSON.parse(JSON.stringify(this.get('attributes')) hasDirtyAttributes works as expected

So how to write some Mixin for a Model or other workaround which on the change of any attribute property will mark hasDirtyAttributes as true. I will update whole object so doesn't matter which property actually was changed.

Same problem: https://discuss.emberjs.com/t/hasdirtyattributes-do-not-work-with-nested-attributes-json-api/15592

existing solution doesn't work for me at all:

  • ember-dirtier
  • ember-data-relationship-tracker
  • ember-data-model-fragments (a lot of changes under the hood and broke my app)

Update:


Some not perfect idea that help better describe what I'm want to achieve: Let say we adding observer to any object fileds:

export default Model.extend({
  init: function(){
    this._super();

    this.set('_attributes', Object.assign({}, this.get('attributes'))); //copy original 
    Object.keys(this.get('attributes')).forEach((item) => {
      this.addObserver('attributes.'+ item, this, this.objectObserver);
    });
  }
...
})

And observer:

objectObserver: function(model, filed){
    let privateFiled = '_' + filed;

    if (model.get(privateFiled) != model.get(filed)) { //compare with last state
      model.set(privateFiled, this.get(filed));
      model.set('attributes', Object.assign({}, this.get('attributes')) );
    }

  }

It's works, but when I change one filed in object due to copying object objectObserver faired again on every filed. So in this key changing every filed in object I mark observed filed as dirty

1

1 Answers

0
votes

The further ember development will reduce using of event listener and two-way binding, actually Glimmer components supports only One-way Data Flow. So to be friendly with future versions of emberusing one-way data flow is good approach in this case to. So In my case as I use ember boostrap solution looks like

<form.element @controlType="textarea" @onChange={{action 'attributeChange'}}

where attributeChange action do all works.

New Glimmer / Octane style based on modifier and looks like:

{{!-- templates/components/child.hbs --}}
<button type="button" {{on "click" (fn @onClick 'Hello, moon!')}}>
  Change value
</button>