Nested object in `DS.attr()` isn't affected by `DS.rollbackAttributes()`

五迷三道 提交于 2019-12-13 11:35:22

问题


I have a model User as follow:

import DS from 'ember-data';

const { attr, Model } = DS;

export default Model.extend({
  name: attr("string"),
  properties: attr(),
});

User.properties is intended to hold a JSON object.

I am updating the model through a form (using ember-one-way-controls) as follow:

{{one-way-textarea
  model.name
  update=(action (mut model.name))}}

{{one-way-textarea
  model.properties.description
  update=(action (mut model.properties.description))}}

I have a button allowing the user to discard the changes by calling a discardChanges action:

actions: {
  discardChanges(model) {
    model.rollbackAttributes();
  },
},

The name attribute changes are correctly discard / reset but the properties attribute is not.

How can I handle this ?


回答1:


Origin of the problem

Ember Data isn't aware of the changes because it uses === operator to compare the dirtied attribute against the original one. If a change has been spotted, Ember Data stores the dirtied attribute key in the _attributes array. We notice this here. Then, when you call DS.rollbackAttributes(), the model looks at the _attributes to acknowledge the attributes to restore. Here it is.

But the hash aren't the same !

JS is all about value passed by reference. Here is an example from Node interpreter:

> var foo = { description: 'hello' }
undefined
> var bar = foo;
undefined
> bar.description = 'bonjour';
'bonjour'
> bar === foo
true

You are modifying the original object.

Solution

A possible solution is to deep-copy your properties object and manually reset it when calling discardChanges.

You can implement it as a service :

import Ember from 'ember';

const { copy, Service } = Ember;

export default Service.extend({
  savedProperties: null,

  finalize() {
    this.set('savedProperties', null);
  },

  start(model) {
    const properties = copy(model.get('properties'));
    this.set("savedProperties", properties);
  },

  undo(model) {
    const savedProperties = this.get('savedProperties');
    for (const property in savedProperties) {
      if (savedProperties.hasOwnProperty(property)) {
        const keyPath = `properties.${property}`;
        model.set(keyPath, savedProperties[property]);
      }
    }
    this.set('savedProperties', null);
  },
});
  • You call start when you enter in edition mode.
  • You call undo when you want to discard the changes.
  • You call finalize when you successfully saved your record.


来源:https://stackoverflow.com/questions/40886068/nested-object-in-ds-attr-isnt-affected-by-ds-rollbackattributes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!