Ember Models - Computed Property

Are computed properties still the best way to have Ember Model fields which are auto-calculated based on values from other fields? Seems that computed properties are being phased out but not sure if there’s any sort of replacement for this particular use case?

To follow up, is there support for computed fields using the native class syntax in models?

IIRC model attributes are auto tracked so ES getters should work just as they would anywhere else with @tracked.

  @attr('string') firstName;
  @attr('string') lastName;

  get fullName() {
    return `${this.firstName} $[this.lastName}`;
  }

and if you need memoization you can use the cached-decorator-polyfill:

  @cached
  get fullName() {
    return `${this.firstName} $[this.lastName}`;
  }

Yeah this is working as expected, I think I was misunderstanding a bit because any @computed fields or getter fields are not setup as Model attributes so are not serialized without some workarounds in the serializer.

Is there any other way to make these auto-generated fields behave as normal model attributes during serialization or is this the correct approach?

Hmmmm what kind of serialization do you mean? Obviously in the contrived example above the getter is part of the “model layer” which sits above the “serialization layer” if you will. So in that case the serializer has no knowledge of it. Do you mean by computing that field in the serializer instead of as a getter? If it’s like a “front-end only” field or something that you are serializing from something on the JSON payload you could either make it an attr just the same as all your other attrs and normalize it on/serializer it off the record on fetch/save (respectively) or you could just make it a tracked property instead of a getter so it is auto-tracked and can be set in the serializer layer.

I think the intention was to have another model attr whose value is calculated on the frontend as opposed to the other fields which are exposed to the user directly via form input. This calculated field would factor into frontend validations so it needs to be accessible when creating local records on the frontend and needs to be serialized in the JSON when creating the entity on the backend.

For the time being I have updated the Serializer serialize to include statements like json.calculatedField = snapshot.record.calculatedField. Another option that I thought of would be to have the getter in the model directly set a separate attr field if that’s possible to bypass the need for customizing the serializer.

Could you just pair the getter with a setter? Definitely seems like a computed is the way to go so you don’t have to involve the serializer at all.

e.g.

  @cached
  get fullName() {
    return `${this.firstName} $[this.lastName}`;
  }
  set fullName(fullName) {
    const [firstName, lastName] = fullName.split(' ');
    this.firstName = firstName;
    this.lastName = lastName;
  }