npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@restspace/svelte-schema-form

v0.1.6

Published

JSON Schema based form generator in Svelte

Downloads

60

Readme

Svelte Schema Form

This is a Svelte implementation of a form generator from JSON Schema. It supports subforms, lists with reordering of items, custom renderer components, and customisable CSS skinning separating layout and look-and-feel.

JSON Schema is a powerful validation/type definition language for JSON data. See this for more information on JSON Schema

How to use

Install with npm

npm install @restspace/svelte-schema-form

Use in a component

<script>
  import { SubmitForm } from '@restspace/svelte-schema-form';
  import '@restspace/svelte-schema-form/css/layout.scss';
  import '@restspace/svelte-schema-form/css/basic-skin.scss';

  let schema = {
	  type: "object",
	  properties: {
		  "x": { "type": "string" }
	  }
  };
  let value = {};

  const submit = (e) => {
	  alert(JSON.stringify(e.detail.value, undefined, 2));
  }
</script>

<SubmitForm {schema} {value} on:submit={submit} />

The layout.css file creates a standard form layout. basic-skin.css adds a very simple skin with fonts, colours etc on top of that. Note, you'll likely need to configure your bundler to interpret importing css to make this work.

The SubmitForm component manages validation of the entered data using the full JSON Schema spec and renders any error messages beside the relevant components. Standard behaviour is that errors are not shown until the Submit button has been clicked at least once.

JSON Schema support

| Feature | Support | |---|---| |title|This property is used to label a field or fieldset, if it's absent a conversion from camel case (myFieldName) to proper case (My Field Name) is done. Newlines in the string are converted to br tags in HTML| |description|This property is shown beside the label as a tooltip using the HTML title attribute or as a subheading for arrays/objects.| |readOnly|This property if present and set to true will disable the editor for this field, only using it for display. All children of this field will also be read only| |type="string"|By default, renders as an input element with type="text"| |minLength, maxLength|Supported in validation| |pattern|Supported in validation| |format|Support for password, email, date, time and date-time via HTML input type| |type="number"|By default, renders as an input element with type="number"| |minimum, maximum|Supported in validation| |exclusiveMinimum, exclusiveMaximum|Supported in validation| |enum|A field with the enum property is instead rendered as a Select element with all the enum options given| |enumText|Custom property to supply display labels for the Select element as an array of strings, one for each enum value| |type="object"|Every object is rendered within an HTML Fieldset element with a form field for each property| |required|Object fields named in the required list have to have a value entered to be valid. Required fields have the required class added to their labels to enable this to be displayed. |type="array"|Every array is rendered within an HTML Fieldset element with controls for adding, deleting, moving and duplicating array items (based on the items property)| |emptyDisplay|Custom property which determines how the array displays if it has no items. false means don't show a header or wrapper. true means show the header and wrapper with no items. A string value means display this message in the wrapper. |controls|Custom property which is a comma separated list of controls including delete, duplicate, reorder, add. Default is all these. A readOnly array has no controls.| |editor|Custom property that lets you pick a custom editor for a schema.| |||

Components

SchemaForm

A group of based on a schema, no submit functionality

import {SchemaForm} from "@restspace/svelte-schema-form";

<SchemaForm
  schema // REQUIRED: JSON schema as an object
  value // REQUIRED: JSON value to initialise the form with, for an empty form use {}
  uploadFiles // Map with keys as property paths to upload editors, values as File objects in those editors
  dirty // Whether the form is dirty i.e. the user has changed it from its initial value
  showErrors // Whether the form should show errors
  components // Map with keys as editor names (value of editor property in schema), values as constructors of editor components
  collapsible // Whether objects and arrays are shown with collapsers which can hide them (default = false)
  componentContext // Data for custom editors
/>

SubmitForm

An HTML form with a submit button and a submit flow

import {SubmitForm} from "@restspace/svelte-schema-form";

<SubmitForm
  schema // REQUIRED: JSON schema as an object
  value // REQUIRED: JSON value to initialise the form with, for an empty form use {}
  uploadFiles // Map with keys as property paths to upload editors, values as File objects in those editors
  uploadBaseUrl // A base URL to which uploaded files are PUT on submit. Subpaths are chosen to be unique.
  uploadNamePattern // A substition pattern for the unique name of this record, e.g. this might be '${email}' for a person's details with a property/field named `email`
  dirty // Whether the form is dirty i.e. the user has changed it from its initial value
  components // Map with keys as editor names (value of editor property in schema), values as constructors of editor components
  collapsible // Whether objects and arrays are shown with collapsers which can hide them (default = false)
  submitText // Text shown in the submit button (defaults to 'Submit')
  submitRequiresDirty // Whether the submit button requires the form to be dirty to submit (default = true)
  componentContext // Data for custom editors
/>

Custom editors

Currency

Setting editor="currency" on a type="number" subschema renders it as a currency field. This automatically inserts a currency symbol in the input field, by default this is a $ but can be changed to another symbol via setting the currencySymbol property on the object passed in to the componentContext prop, to e.g. '£'. You can also specify a custom formatting function which takes a value of type number and returns a string and set the formatCurrency property on componentContext to this function.

Radio

Setting editor="radio" on a subschema with enum set renders the enum as radio buttons instead of a select.

Upload

Setting editor="upload" on a type="string" subschema means that this property will be rendered as a file uploader. This component requies a SubmitForm. The file uploader allows files to be dragged onto it, or to be clicked to open a file dialog. Files are sent on submit via a PUT request to a path composed:

<uploadBaseUrl>/<uploadName>/<path>/<filename of file>
  • uploadBaseUrl is the prop on SubmitForm
  • uploadName is the uploadNamePattern with form field value(s) substituted in for ${<property path>} codes so as to create a name that will be unique for each stored record
  • path is the property path of the upload control with dot separators and array poitions just being an index with no square brackets e.g. profilePics.3.image

After successful submit, the property value for the editor is set to the url where the file was uploaded. The uploader has a button at the right bottom to switch modes to show a text input field with the url of the stored file.

Autocomplete

Setting editor="autocomplete" on a type="string" subschema means this property will be rendered as an autocomplete dropdown. The autocomplete component is a text box which on each keystroke sends the entered text to a remote url to get a list of matching items which are then shown as a dropdown. The user can choose one of the displayed items at any point.

The schema needs an additional property url set to the base url for remote querying. Example subschema:

{
	"type": "string",
	"editor": "autocomplete",
	"url": "https://mysite.com/autocompletes"
}

To this url is added the query string item match=xyz where xyz is the current text in the search box to match on. A GET request is made to the result. The url should respond with an application/json body which can either be

[ "dropdown item 1", "dropdown item 2", ... ]

or

[
	{
		"id": "1234",
		"text": "An item title",
		"image": "https://images.com/an-image.jpg"
	}, ...
]

In the latter case, the id field is returned as the value of the editor, the text field determines the text shown in the field, and the optional image url gives an image to display alongside the text.

List Detail

Setting editor="list-detail" on a type="array" subschema whose items are type="object" shows the list of objects in a listing grid which when a row is selected, switches to the normal editor for the object selected. It also provides heading-click view ordering (without mutating the order of the underlying data list). It responds to the emptyDisplay and controls custom properties defined for an array.

The type="object" subschema can have two optional custom schema properties:

  • headings: an array of property names which are included as columns in the list. Defaults to all columns.
  • defaultSort: an object with properties field which specifies the default heading field to sort on, and direction which can be "asc" or "desc" to specify the direction of the default sort.

Custom rendering components

Svelte Schema Form can override or add rendering components at any level by supplying a map of component type names and component classes.

For example components, look in the /src/lib/editors directory. As an illustration, consider the Number.svelte default editor:

<script lang="ts">
	import type { CommonComponentParameters } from "../types/CommonComponentParameters";
	export let params: CommonComponentParameters;
	export let schema: any;
	export let value: any;
</script>

<!-- event which calls pathChanged should be after all bindings so 'value' will have been updated -->
<svelte:component this={params.components['fieldWrapper']} {params} {schema}>
	<input id={params.path.join('.')} name={params.path.join('.')}
		type="number" value={value || ''}
		disabled={schema.readOnly}
		on:input={ev => {
			let val = parseFloat(ev.currentTarget.value);
			params.pathChanged(params.path, isNaN(val) ? undefined : val);
		}}
	/>
</svelte:component>

The component needs to have the 3 props shown in this component. schema and value are the local parts of the full schema and value which need to be rendered by this component. params contains a number of constant values defining the component including params.pathChanged which is a function that needs to be called with the property path to the value the component is rendering (this is params.path) and the new value when the value of the form field is changed.

Note how the editor supports the readOnly attribute by disabling the editor if set.

The <svelte:component> component wrapping the markup renders the default FieldWrapper.svelte component around the actual editor: this adds the field's standard label and error message.

An example of how to configure a custom component:

<script>
  import MyEditor from "./MyComponent.svelte";

  let components = {
	  "myEditor": MyEditor
  };
  ...
</script>

<SubmitForm {schema} {value} on:submit={submit} {components} />

You'd then make use of this custom editor component in a schema like this:

{
	"type": "object",
	"properties": {
		"myField": {
			"type": "string", 
			"editor": "myEditor"
		}
	}
}

The key in the components map is matched to, in priority order, the editor property, then the format property, then the type property. This means you can also substitute editors for field groupings, which is more tricky. Work from the Array.svelte and Object.svelte default editor components in the repo.