Description
@Anthropic Hi Anthropic
I just completed a schema based form editor for angular 2 for a future project and I would like to discuss my solution with you - if you are interested? - since I think some of my ideas might be useful for this project and I am interested in co-operation.
My proposed solution consist of:
- A generic gui model in typescript that can be easily consumed and used to draw a form. The gui model only contains representational data + mappings back to the schema. No validation stuff.
- A typescript translator that reads a JSON schema file and translates it into a gui model.
- A web form in angular 2 that process the gui model, shows the corresponding form and calls into AJV (https://github.com/epoberezkin/ajv) at roughly each keystroke to validate and show validation errors.
This solution is very simple yet works fine for my yet-to-be announced OS project. See example of an Angular2 form below using this approach. The code could be extended to work with any web framework with modifications to step 3. The main idea, which I think could affect this core project is to introduce a gui model - or a IR (intermediate representation) in other words - as a translation target for the core AND to simplify things by not putting validations stuff into it but still requiring a fast schema validator to be used in the gui rather than standard validation api's for form elements.
Example of dynamic from produced from a json schema:
An example of how an instance of the corresponding gui model could look like is shown below:
const complex_gui_model1: SettingsGuiModel = {
kind: 'group',
name: '',
controlType: 'group',
label: '',
tooltip: '',
settingsObjectPath: '',
required: true,
elements: [
{ kind: 'group', name: 'authentication', controlType: 'group', label: 'Authentication', tooltip: 'an authentication description here', settingsObjectPath: 'authentication', isRoot: false, required: true,
elements: [ { kind: 'field', name: 'user', controlType: 'input', label: 'User', tooltip: 'a username', settingsObjectPath: 'authentication.user', defaultValue: '', values: undefined, required: true, type: 'string', subType: 'none' },
{ kind: 'field', name: 'password', controlType: 'input', label: 'Password', tooltip: 'a password', settingsObjectPath: 'authentication.password', defaultValue: '', values: undefined, required: true, type: 'string', subType: 'none' },
{ kind: 'field', name: 'scheme', controlType: 'input', label: 'scheme', tooltip: '', settingsObjectPath: 'authentication.scheme', defaultValue: 'basic', values: undefined, required: true, type: 'string', subType: 'none' },
{ kind: 'field', name: 'preemptive', controlType: 'yesno', label: 'preemptive', tooltip: '', settingsObjectPath: 'authentication.preemptive', defaultValue: true, values: undefined, required: true, type: 'boolean', subType: 'none'}
]
},
{ kind: 'group', name: 'server', controlType: 'group', label: 'Server', tooltip: '', settingsObjectPath: 'server', isRoot: false, required: true,
elements: [ { kind: 'field', name: 'host', controlType: 'input', label: 'host', tooltip: '', settingsObjectPath: 'server.host', defaultValue: '', values: undefined, required: true, type: 'string', subType: 'none' },
{ kind: 'field', name: 'port', controlType: 'input', label: 'port', tooltip: '', settingsObjectPath: 'server.port', defaultValue: 80, values: undefined, required: true, type: 'integer', subType: 'none' },
{ kind: 'field', name: 'protocol', controlType: 'dropdown', label: 'protocol', tooltip: '', settingsObjectPath: 'server.protocol', defaultValue: 'http', values: ['http', 'ftp'], required: true, type: 'string', subType: 'none' }
]
}
],
errors: [],
isRoot: true
};
And the corresponding source schema looks like is shown here:
{
'$schema': 'http://json-schema.org/draft-04/schema#',
'type': 'object',
'properties': {
'authentication': {
'type': 'object',
'title': 'Authentication',
'description': 'an authentication description here',
'properties': {
'user': {
'type': 'string',
'minLength': 1,
'default': '',
'title' : 'User',
'description': 'a username',
},
'password': {
'type': 'string',
'minLength': 1,
'default': '',
'title' : 'Password',
'description': 'a password',
},
'scheme': {
'type': 'string',
'default': 'basic'
},
'preemptive': {
'type': 'boolean',
'default': true
}
},
'required': [
'user',
'password',
'scheme',
'preemptive'
]
},
'server': {
'type': 'object',
'title': 'Server',
'properties': {
'host': {
'type': 'string',
'default': ''
},
'port': {
'type': 'integer',
'multipleOf': 1,
'maximum': 65535,
'minimum': 0,
'exclusiveMaximum': false,
'exclusiveMinimum': false,
'default': 80
},
'protocol': {
'type': 'string',
'default': 'http',
'enum' : ['http', 'ftp']
}
},
'required': [
'host',
'port',
'protocol'
]
}
},
'required': [
'authentication',
'server'
],
'additionalProperties': false
}
Let me know if you think this sounds interesting?. If so, we could co-operate on a "standardised" gui model and a translator from json schema to that model. As noted, I have an initial version working.
/Morten