Define multiple model subclass type via crud manager for a single store
Posted: Thu Jan 05, 2023 4:26 pm
by jarmen
Our resource store contains two different types of resources that are represented by different subclasses of ResourceModel. e.g. TypeAResourceModel and TypeBResourceModel. The incoming data has a discriminator defining which type of model should be created. Is there a specific field this can be mapped to so that the correct type of model is constructed?
We are familiar with the modelClass field for a store, however that only allows us to specify a single model class.
This would be similar to how the column store provides a 'type' specification allowing configuration of different column types that utilize different Column classes derived from Model
Re: Define multiple model subclass type via crud manager for a single store
Posted: Fri Jan 06, 2023 3:30 am
by alex.l
Store cannot contain records with different model classes. By design, a store contains a set of records with the one data model class, same as database table.
If you want to have "typeA" and "typeB" records, you can add a new field "type" to your data model and specify the type in there. After that check that flag in your code and fill-in fields that required for this type.
Re: Define multiple model subclass type via crud manager for a single store
Posted: Fri Jan 06, 2023 10:13 am
by mats
We actually should support this by using a custom createRecord function on the Store, see below:
store : {
// Default model is a Gate
modelClass : Gate,
readUrl : 'data/kastrup-airport.json',
autoLoad : true,
createRecord(data, skipExpose = false, rawData = false) {
let modelClass = this.modelClass;
if (data.type === 'terminal') {
modelClass = Terminal;
}
return new modelClass(data, this, null, skipExpose, false, rawData);
}
},
Re: Define multiple model subclass type via crud manager for a single store
Posted: Fri Jan 06, 2023 10:49 am
by jarmen
Thank you Mats, this should work for us.
It appears the typescript exports may be incorrect. This is the signature we see:
Both types would use the TerminalResourceModel class. We can get around this by wrapping our children in new TerminalResourceModel, however it would be nice if we didn't have to do this extra step.
Re: Define multiple model subclass type via crud manager for a single store
Posted: Sat Jan 14, 2023 11:45 am
by mats
How can I reproduce this? Tests pass just fine here:
t.iit('Initialize with tree data', t => {
const store = new MixedStore({
tree : true,
data : [
{
type : 'a',
name : 'Terminal',
children : [
{ type : 'b', name : 'Gate A' }
]
}
]
});
t.isInstanceOf(store.rootNode.firstChild, ModelA);
t.isInstanceOf(store.rootNode.firstChild.firstChild, ModelB);
});
Re: Define multiple model subclass type via crud manager for a single store
Posted: Sat Jan 14, 2023 7:54 pm
by jarmen
I'll see if I can get an example setup for you. The use case where this seems to be an issue is when we would say
Re: Define multiple model subclass type via crud manager for a single store
Posted: Mon Jan 16, 2023 10:28 am
by alex.l
Waiting for your testcase. meanwhile I tested with your code and it still passed
t.iit('Initialize with tree data', t => {
const store = new MixedStore({
tree : true,
data : [
{
id : 1,
type : 'a',
name : 'Terminal',
children : [
{ id : 2, type : 'b', name : 'Gate A' }
]
}
]
});
store.first.appendChild({id : 3, type : 'a', children : [ { id : 4, type : 'b'} ] })
t.isInstanceOf(store.rootNode.firstChild, ModelA);
t.isInstanceOf(store.rootNode.firstChild.firstChild, ModelB);
t.isInstanceOf(store.getById(3), ModelA);
t.isInstanceOf(store.getById(4), ModelB);
});
Re: Define multiple model subclass type via crud manager for a single store
Posted: Fri Jan 27, 2023 11:29 pm
by jarmen
Here's the code I was able to use to reproduce. I see that we should be passing in a reference to 'this' in the model constructor, however the exported typescript model's constructor only accepts a single argument for data. Is there a way to inform the model which store it belongs to during construction in typescript?
Thanks, Jon
Tree demo
Code editor
Download code
app.module.js
Auto apply
import { SchedulerPro, ResourceModel, StringHelper } from '../../build/schedulerpro.module.js';
import shared from '../_shared/shared.module.js';
class Gate extends ResourceModel {
get doWork() { return 'gate model'; }
}
class Terminal extends ResourceModel {
get doWork() { return 'terminal model'; }
}
new SchedulerPro({
appendTo : 'container',
eventColor : null,
eventStyle : null,
resourceStore: {
modelClass: Gate,
createRecord(data, skipExpose = false, rawData = false) {
let modelClass = this.modelClass;
if (data.type === 'terminal') {
modelClass = Terminal;
}
// Works
//return new modelClass(data, this);
// Does not Work
return new modelClass(data);
}
},
features : {
tree : true,
},
rowHeight : 45,
barMargin : 5,
columns : [
{
type : 'tree',
text : 'Name',
width : 220,
field : 'name'
}, {
text : 'Model Type',
width : 90,
field : 'doWork'
}
],
viewPreset : 'hourAndDay',
resources: [{
name: 'Terminal A',
type: 'terminal',
children: [{
name: 'Gate A1',
type: 'gate'
}]
}]
});
Idle