Facing cannot read property 'setDirtyAttribute' of null
even if you use YourModel.create({...})
in ember-typescript-cli
to create a EmberObject.
Model:
import DS from 'ember-data';
import {computed} from "@ember/object";
export default class Person extends DS.Model {
@DS.attr() firstName!: string;
@DS.attr() lastName!: string;
@DS.attr() age!: number;
@DS.attr() desc?: string;
@computed("firstName", "lastName")
public get fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
Route:
export default class Persons extends Route {
@service() public store!: DS.Store;
constructor() {
super(...arguments);
const persons: Person[] = [
Person.create({firstName: "first1", lastName: "last1", age: 10}),
Person.create({firstName: "first2", lastName: "last2", age: 320}),
Person.create({firstName: "first3", lastName: "last3", age: 30}),
];
persons.forEach(p => this.store.createRecord('person', p));
}
}
Get error when enter the page:
Uncaught TypeError: Cannot read property 'setDirtyAttribute' of null
at Person.set (-private.js:144)
at ComputedProperty._set (metal.js:3543)
at ComputedProperty.setWithSuspend (metal.js:3532)
at ComputedProperty.set (metal.js:3503)
at initialize (core_object.js:67)
at Function.create (core_object.js:692)
at new Persons (persons.js:23)
at Function.create (core_object.js:684)
at FactoryManager.create (container.js:549)
at instantiateFactory (container.js:359)
So I have to use things like this.store.createRecord('person', {firstName: "first1", lastName: "last1", age: 10})
rather than this.store.createRecord('person', <a Person class instance>)
, which is not typescript-ish at all. So I hope to find a more elegant way to combine the ember feature to typescript, rather than use any
or bare object
everywhere.
Any advice?
The documentation of Ember Data is quite clear that you shouldn't use Model.create({})
. It's not only private API but even documented that instances of models should only be created using the store service:
Create should only ever be called by the store. To create an instance of a Model in a dirty state use store.createRecord.
To create instances of Model in a clean state, use store.push
Ember Data's public APIs should work well with Typescript by default. The known and documented bug in ember-data@3.11.0
should have been fixed in a later point release.
Please refer to Ember CLI TypeScript's documentation about Ember Data support for supported setup.