Invoking a component with a computed property argument results in "EmberObject.create no longer supports defining computed properties"

Hi, we’re upgrading our ember app to 3.6.1 (from 3.5.1) as part of our roadmap to get back on the latest version of ember.

After the upgrade we started seeing an error “EmberObject.create no longer supports defining computed properties. Define computed properties using extend() or reopen() before calling create().”

What’s weird is that in this case the error is coming from a component invocation.

From the stack trace, the error is occurring in CurlyComponentManager.create when it tries to create a child component referenced in a parent component’s template:

{{loan-information/expanded/cell
  data=propertyType
  type='string'
}}

The child component’s definition is very simple.

@tagName('td')
@classNames('tm-TableFact-cell')
export default class LoanInformationExpandedTableCellComponent extends Component {}

In the parent component, propertyType is defined as an alias to an ember data model property.

export default class LoanInformationSubjectPropertyComponent extends Component {
  subjectProperty: SubjectPropertyModel;
  @alias('subjectProperty.propertyType') propertyType;
  ...

The error is happening because the ‘data’ property being passed into the child component is failing the check:

true && !!(value instanceof _metal.ComputedProperty) && (0, _debug.assert)('EmberObject.create no longer supports defining computed ' + 'properties. Define computed properties using extend() or reopen() ' + 'before calling create().', !(value instanceof _metal.ComputedProperty));

The value of course comes from a computed property in the parent component, but it seems wrong that this check is failing when it’s passed in as a property to a child component in a template. What am I missing?

Some updates:

  • this issue also occurs when I try ember versions 3.7 as well as 3.8.
  • converting to positional component arguments makes the error go away, but this problem is affecting multiple components in our codebase and some of them have too many arguments for the positional notation to be ergonomic
  • switching from decorator to helper function syntax does not make the problem go away

Yeah, it doesn’t look like you’re doing anything wrong. Seems like maybe a bug. How is propertyType defined on the ember data model?

value instanceof _metal.ComputedProperty means you’re somehow not getting the value of the computed property, but the internal object that tracks the computed property. I don’t recall at which release this behavior changed, but in older Ember if you tried to access a computed property directly (this.someThing) without using get you’d get that ComputedProperty object rather than the value. On newer Ember you always get the value, whether or not you use get.

Another idea is to check on your ember-data version. If your ember-data is older than your ember that could be the source of this class of problem, because ember-data may be doing deprecated things.

Thanks @ef4 for your response. Your question about propertyType was a good lead. It turns out that the issue was with the model definition. The model in question was defined like

export default class RealEstateOwnedModel extends PropertyModel {
  propertyType = DS.attr('string');
  ..
}

Switching it to the following made the error go away.

export default class RealEstateOwnedModel extends PropertyModel.extend({
  propertyType: DS.attr('string'),
  ..
}) {}

Having types via typescript and classes is nice, but with ember/ember-data not being fully typescripted yet some of the transitional syntax required is tricky to get right.

1 Like

Please see this official blog post on using classes and the Ember 3.10 release blog post discussion of decorators—they should guide you onto the right path for TS as well as for JS! The reason this is a problem is covered in part here.

You can write this using decorators, with official support, like this:

import DS from 'ember-data';
const { attr } = DS;

export default class RealEstateOwnedModel extends PropertyModel {
  @attr('string')
  propertyType?: string;
  ..
}
1 Like