UNPKG

@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
<!DOCTYPE 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>