@mistio/mist-form
Version:
A Webcomponent that renders a form defined by a JSONSchema & an optional UISchema spec
272 lines (257 loc) • 8.73 kB
HTML
<html lang="en-GB">
<head>
<meta charset="utf-8" />
<style>
body {
background: #fafafa;
}
div#jsonSchema {
width: 100%;
}
mist-form {
padding: 25px;
/* width: 100%; */
}
div#form {
width: 60%;
}
div#form > mist-form {
margin: 32px;
}
div.editor {
min-height: 300px;
max-height: 600px;
}
div#jsonSchema > .editor {
min-height: 400px;
}
vaadin-tab {
text-transform: capitalize;
}
</style>
</head>
<body>
<h1>mist-form</h1>
<div id="demo"></div>
<script type="module">
import { html, render } from 'lit';
import {repeat} from 'lit/directives/repeat.js';
import '../mist-form.js';
import loader from '@monaco-editor/loader';
import '@polymer/paper-styles/demo-pages.js';
import '@polymer/paper-spinner/paper-spinner.js';
import '@polymer/iron-ajax/iron-ajax.js';
import '@vaadin/tabs';
import '@vaadin/split-layout';
import '@vaadin/select';
import '@vaadin/item';
import '@vaadin/list-box';
import '@vaadin/combo-box';
let presets = [
{id: 'simple'},
{id: 'subform'},
{id: 'nested'},
{id: 'arrays'},
{id: 'numbers'},
{id: 'widgets'},
{id: 'ordering'},
{id: 'references'},
{id: 'custom'},
{id: 'errors'},
{id: 'examples'},
{id: 'large'},
{id: 'datetime', title: "Date & Time"},
{id: 'validation'},
{id: 'files'},
{id: 'single'},
{id: 'customarray', title: "Custom Array"},
{id: 'customobject', title: "Custom Object"},
{id: 'alternatives'},
{id: 'propdeps', title: "Property dependencies"},
{id: 'schemadeps', title: "Schema dependencies"},
{id: 'addprops', title: "Additional Properties"},
{id: 'anyof', title: "Any Of"},
{id: 'oneof', title: "One Of"},
{id: 'allof', title: "All Of"},
{id: 'ifthenelse', title: "If Then Else"},
{id: 'nullfields', title: "Null Fields"},
{id: 'nullable'},
{id: 'errorschema', title: "Error Schema"},
{id: 'defaults'},
];
if (document.location.search.startsWith('?mist')) {
presets = [
{id: 'mist/addkey', title: "Add key"},
{id: 'mist/addcloud', title: "Add cloud"}
]
}
export const debouncer = function (callback, wait) {
let timeout = 1000;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(function () {
callback.apply(this, args);
}, wait);
};
};
let jsonSchemaEditor; let uiSchemaEditor; let formDataEditor;
loader.init().then(monaco => {
jsonSchemaEditor = monaco.editor.create(document.querySelector("div#jsonSchema > .editor"), {
value: JSON.stringify(document.querySelector('mist-form').jsonSchema, null, 2),
language: 'json',
automaticLayout: true
});
const jsonSchemaValue = jsonSchemaEditor.getValue();
if (jsonSchemaValue)
document.querySelector('mist-form').jsonSchema = JSON.parse(jsonSchemaValue);
jsonSchemaEditor.onDidChangeModelContent(
debouncer(
() => {
const data = JSON.parse(jsonSchemaEditor.getValue());
console.log(jsonSchemaEditor.getValue());
document.querySelector('mist-form').jsonSchema = data;
}, 250)
);
document.querySelector('mist-form').addEventListener('json-schema-changed', (e) => {
jsonSchemaEditor.setValue(JSON.stringify(e.detail.value, null, 2));
});
});
loader.init().then(monaco => {
uiSchemaEditor = monaco.editor.create(document.querySelector("div#uiSchema > .editor"), {
value: JSON.stringify(document.querySelector('mist-form').uiSchema, null, 2),
language: 'json',
automaticLayout: true
});
const uiSchemaValue = uiSchemaEditor.getValue();
if (uiSchemaValue)
document.querySelector('mist-form').uiSchema = JSON.parse(uiSchemaValue);
uiSchemaEditor.onDidChangeModelContent(
debouncer(
() => {
console.log(uiSchemaEditor.getValue());
document.querySelector('mist-form').uiSchema = JSON.parse(uiSchemaEditor.getValue());
}, 250)
);
document.querySelector('mist-form').addEventListener('ui-schema-changed', (e) => {
uiSchemaEditor.setValue(JSON.stringify(e.detail.value, null, 2));
});
});
loader.init().then(monaco => {
formDataEditor = monaco.editor.create(document.querySelector("div#formData > .editor"), {
value: '',
language: 'json',
automaticLayout: true
});
// const formDataValue = formDataEditor.getValue();
// if (formDataValue)
// document.querySelector('mist-form').formData = JSON.parse(formDataValue);
formDataEditor.onDidChangeModelContent(debouncer((e) => {
// debugger;
const newValue = formDataEditor.getValue();
try {
document.querySelector('mist-form').formData = JSON.parse(newValue);
} catch(e) {
if (document.querySelector('mist-form').formData !== newValue) {
document.querySelector('mist-form').formData = newValue;
}
}
document.querySelector('mist-form').validate();
}, 150));
document.querySelector('mist-form').addEventListener('form-data-changed', function(e) {
// debugger;
let newValue = this.domValue;
switch (typeof(newValue)) {
case "string":
break;
case "object":
if (newValue.length) {
newValue = JSON.stringify(newValue, null, 2);
} else {
newValue = JSON.stringify({...JSON.parse(formDataEditor.getValue()), ...newValue}, null, 2);
}
break;
default:
}
if (formDataEditor.getValue() !== newValue) {
formDataEditor.setValue(newValue);
}
});
updateTab();
});
function updateTab(e) {
const preset = e ? e.detail.value : 0;
const url = `${presets[preset].id }.json`;
fetch(url)
.then(response => response.json())
.then(async body => {
const form = document.querySelector('mist-form#playground');
form.jsonSchema = body.jsonSchema;
form.uiSchema = body.uiSchema;
form.formData = body.formData;
if (jsonSchemaEditor) jsonSchemaEditor.setValue(JSON.stringify(body.jsonSchema || body, null, 2));
if (uiSchemaEditor) uiSchemaEditor.setValue(JSON.stringify(body.uiSchema || {}, null, 2));
if (formDataEditor) formDataEditor.setValue(JSON.stringify(body.formData || {}, null, 2));
})
.catch(error => {
console.error('Error loading spec:', error);
});
}
render(
html`
<vaadin-tabs @selected-changed="${updateTab}">
${repeat(presets, item => item, (item) => html`<vaadin-tab>${item.title || item.id}</vaadin-tab>`)}
</vaadin-tabs>
<vaadin-split-layout>
<div id="schemas" class="column">
<vaadin-split-layout orientation="vertical">
<div id="jsonSchema">
<h3>JSON Schema</h3>
<div class="editor"></div>
</div>
<vaadin-split-layout>
<div id="uiSchema">
<h3>UI Schema</h3>
<div class="editor"></div>
</div>
<div id="formData">
<h3>Form data</h3>
<div class="editor"></div>
</div>
</vaadin-split-layout>
</div>
<div id="form" class="column">
<h3>Rendered form</h3>
<mist-form
id="playground"
>
<iron-ajax
slot="formRequest"
id="formAjax"
url="/api/v1/products"
contentType="application/json"
.submit=${this}
method="POST"
handle-as="json"
@mist-form-request=${function (e) {
this.body = JSON.stringify(e.detail.payload);
this.generateRequest();
}}
@response=${() => {
console.log('on response');
}}
@request=${() => {
console.log('on request');
}}
@error=${() => {
console.log('on error');
}}
></iron-ajax>
</mist-form>
</div>
</vaadin-split-layout>`,
document.querySelector('#demo')
);
</script>
</body>
</html>