Package Exports
- @byte-power/json-press
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@byte-power/json-press) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
使用说明
简介
JSON Press 是一款能将描述数据结构的 JSON Schema 转换为相应的 HTML 表单的前端工具库。
它能快速生成以 JSON 文件作为产出物的可交互、有约束、易校验的 HTML 表单,可以对应用、游戏提供简洁快速的配置支持,避免使用原始表单组件进行大量重复的页面布局和功能开发,提高生产效率。
它是 json-editor/json-editor 的 fork 版本,在其基础上进行了美化、增强和修正(下文用 Press 代指来注明修改之处)。
安装
推荐以 npm 方式安装
$ npm install @byte-power/json-press
引入
以 ES6 模块形式
import {JSONEditor} from '@byte-power/json-press';
以 CommonJS 形式
let {JSONEditor} = require('@byte-power/json-press');
使用
let element = document.getElementById('editor');
let editor = new JSONEditor(element, options);配置
编辑器的配置分为全局配置和局部配置。
全局配置
全局配置可以通过默认值形式或者实例初始化时传入参数来对编辑器的默认配置进行设置和修改
默认值形式
JSONEditor.defaults.options.disable_edit_json = 1
实例化传参形式
const editor = new JSONEditor(element, {
//...
disable_edit_json: 1
});推荐使用实例化传参方式进行配置:因为在需传入多条配置的情景下,使用默认值形式逐条设置会比较繁琐;而使用单个对象进行整体赋值又容易覆盖 default 配置,造成其他值丢失
配置项列表
| 选项 | 描述 | 默认值 | 全局 | 局部 |
|---|---|---|---|---|
| schema | 设置编辑器的 schema 值,支持规范的 v3、v4 版本 | {} | √ | |
| startval | 设置编辑器的初始值,该 JSON 值应该符合 schema 规则设定 | null | √ | |
| theme | 设置编辑器的 CSS 主题引擎 | 'html' | √ | |
| iconlib | 设置编辑器的图标库 | null | √ | |
| template | 设置编辑器的 JS 模板引擎 | 'default' | √ | |
| form_name_root | 设置表单的根名称 | 'root' | √ | |
| object_layout | 设置 object 类型的布局展示方式,有效值包括 'table' | 'normal' | √ | |
| ajax | 是否允许编辑器通过 ajax 加载 schema 内 $ref 字段所设置的外部 schema 文件 | false | √ | |
| refs | 一个包含 schema 定义的 url 地址,用于预加载外部 schema | {} | √ | |
| max_depth | 设置 schema 的渲染层级,0 表示渲染所有 | 0 | √ | |
| use_default_values | 是否按字段的 type 属性设置来预设其初始值,否则该字段为 undefined | true | √ | |
| show_errors | 界面显示校验错误信息的时机,有效值包括 'interaction', 'change', 'always', 'never' | 'interaction' | √ | |
| disable_array_add | 是否禁用 array 类型的 add row 按钮 |
false | √ | √ |
| disable_array_delete | 是否禁用 array 类型的 delete row 按钮 |
false | √ | √ |
| disable_array_delete_all_rows | 是否禁用 array 类型的 delete all rows 按钮 |
false | √ | √ |
| disable_array_delete_last_row | 是否禁用 array 类型的 delete last row 按钮 |
false | √ | √ |
| disable_array_reorder | 是否禁用 array 类型每个元素下的 move up 和 move down 按钮 |
false | √ | √ |
| enable_array_copy | 是否显示 array 类型每个元素下的 copy 按钮 |
false | √ | |
| array_controls_top | 是否把 array 类型的控制按钮(add/delete)显示在列表上方 | false | √ | √ |
| prompt_before_delete | 是否在删除 array 类型元素之前显示确认提示 | true | √ | |
| disable_collapse | 是否禁用 object 和 array 类型的 collapse 按钮 |
false | √ | √ |
| disable_edit_json | 是否禁用 object 类型的 Edit JSON 按钮 |
false | √ | √ |
| disable_properties | 是否禁用 object 类型的 Edit Properties 按钮 |
false | √ | √ |
| remove_button_labels | 是否移除控制按钮内的文本,在 iconlib 设置时有效 | false | √ | |
| no_additional_properties | object 是否能显示 properties 字段定义外的其他属性 | false | √ | |
| required_by_default | schema 字段是否默认为 required (不用显式设定 required 属性) | false | √ | |
| display_required_only | 是否仅显示 required 的字段 | false | √ | |
| show_opt_in | 是否将非 required 的字段设置为可选项(其标题旁会加入切换开关) | false | √ | |
| keep_oneof_values | 切换 oneOf 时是否保留其内部值 | true | √ | |
| enum_source_value_auto_select | 是否在枚举类型上下移动待选项时,保留选中值 | true | √ | |
| compact | 是否显示当前项的 label | false | √ | |
| collapsed | 是否默认折叠 object 和 array 类型的数据 | false | √ | |
| enum_titles | 设置枚举类型的选项标题,用于定义 enum 属性列表中每项值的对应显示标题 | [] | √ | |
| hidden | 是否在界面隐藏当前项(getValue 获取值不受影响) | false | √ | |
| remove_empty_properties | 是否移除空属性值,即 getValue 时不会获取为 falsy 值的相关属性,用于 object 类型 | false | √ | |
| grid_columns | 设置当前项占据的栅格数(1 至 12),用于 object 类型的 grid 布局 | √ | ||
| expand_height | 是否自动扩展当前输入框的高度以适应内容,用于 textarea | false | √ | |
| input_height | 设置当前输入框的高度,支持有效 css 值,用于 textarea | √ | ||
| input_width | 设置当前输入框的宽度,支持有效 css 值,用于 string、number、integer | √ |
局部配置
局部配置是通过当前项 options 属性来添加。
let schema = {
compact: {
type: 'string',
options: {
// option
compact: true
}
},
hidden: {
type: 'string',
options: {
// option
hidden: true
}
},
multi: {
type: 'object',
format: 'grid',
properties: {
color: {
type: 'integer',
enum: [1, 2, 3, 4, 5],
options: {
// option
grid_columns: 6,
// option
enum_titles: ['Black', 'Red', 'Green', 'Blue', 'White']
}
},
intro: {
type: 'string',
format: 'textarea',
options: {
// option
grid_columns: 6,
// option
expand_height: true
}
},
empty: {
type: 'string'
}
},
options: {
// option
collapsed: true,
// option
remove_empty_properties: true
}
},
list: {
type: 'array',
format: 'table',
items: {
type: 'object',
properties: {
name: {
type: 'string',
options: {
// option
input_width: '150px'
}
},
id: {
type: 'string',
format: 'textarea',
options: {
// option
input_height: '60px'
}
}
}
}
}
};读写数据
整体操作
编辑器提供了 setValue 和 getValue 方法对整个实例进行存值(一般用于编辑器初始化时)和取值(一般用于保存最终输入结果)
editor.setValue({name: 'John Smith'});
const value = editor.getValue();
console.log(value.name);注:也可以使用编辑器的 startval 选项,在初始化时,进行默认值的设定。
局部操作
除了针对整个编辑器进行值的存取外,还能指定 schema 的单个节点进行相应操作。
// 首先按路径获取编辑器的子节点
const name = editor.getEditor('root.name');
// 路径无效时,getEditor 会返回 null,避免报错
if (name) {
name.setValue('John Smith');
console.log(name.getValue());
}校验数据
编辑器会对用户输入进行校验和限制,避免输入无效内容。校验的方式包括:输入状态提示、控制按钮的启用和禁用等。
在某些情况下,输入数据可能还是会和 schema 规则有冲突,但是没有得到显式提醒,这时候就可以使用编辑器提供的 validate 方法,进行自定义的校验和相应处理
const errors = editor.validate();
if (errors.length) {
// errors 是一个对象组成的数组,对象属性包括`path`、`property`、`message`
console.log(errors);
}validate 方法默认使用编辑器的当前值进行校验,可以传入自定义的值进行验证。
const errors = editor.validate({...});监听数据
编辑器提供了 change 事件,可以在数据变动时触发。
let handle = () => {
// 相应处理
};
editor.on('change', handle);
editor.off('change', handle); // 第二参数不传的话,默认停止监听所有事件除了监听整个编辑器,也可以通过指定路径,进行子节点的监听。
editor.watch('root.name', () => {
// 相应处理
});
editor.unwatch('root.name', handle); // 第二参数不传的话,默认停止监听该节点上所有事件启用、停用编辑器
编辑器提供了一系列的方法来进行整体和单独节点的启用和停用操作。
// 禁止编辑整个表单
editor.disable();
// 禁止编辑指定路径的表单项
editor.getEditor('root.name').disable();
// 允许编辑整个表单
editor.enable();
// 允许编辑指定路径的表单项
editor.getEditor('root.name').enable();
// 检查整个表单的可编辑状态
if (editor.isEnabled()) {
alert('ok');
}
// 停用指定路径的表单项(即整体数据不再包含该字段值,相当于 show_opt_in 选项打开,并且未勾选当前项)
// 仅支持非 required 项
editor.getEditor('root.name').deactivate();
// 启用指定路径的表单项
editor.getEditor('root.name').activate();
// 从 DOM 树移除当前编辑器节点
editor.destroy();数据类型使用详解
目前 schema 支持的数据包括基础类型 type 和扩展格式 format,通过这两种属性的结合设置和使用,从而满足更丰富更个性化的数据格式及交互需求。
基础类型
- string
- number
- integer
- boolean
- object
- array
- null
- info
- signature
扩展格式
- textarea (基于 string 扩展)
- date (基于 string 扩展)
- time (基于 string 扩展)
- datetime-local (基于 string 扩展)
- color (基于 string 扩展)
- starrating (基于 string 扩展)
- hidden (基于 string 扩展)
- uuid (基于 string 扩展)
- range (基于 number 扩展)
- rating (基于 integer 扩展)
- checkbox (基于 boolean 扩展)
- grid (基于 object 扩展)
- table (基于 array 扩展)
- tabs (基于 array 扩展)
- radio (基于 string/number/integer + enum 扩展,即单选)
- checkbox (基于 array + enum 扩展,即多选)
- select2 (基于 enum 扩展,单选多选都支持)
汇总
| type | format | enum | 备注 |
|---|---|---|---|
| string |
textarea
starrating hidden uuid |
无 | |
|
date
time datetime-local |
无 | 通过 flatpickr 支持 | |
| color | 无 | 通过 colorpicker 支持 | |
| radio | 有 | ||
| boolean | checkbox | ||
| number | range | ||
| integer | rating | ||
| array | checkbox | 有 | |
|
table
tabs |
无 | ||
| object | grid | ||
| 任意类型均可 | select2 | 有 | 通过 select2 支持 |
| null | |||
| info | |||
| signature |
string
最基础的数据类型,通过指定 format 还能支持更多的交互和数据子类型。
基础用法
let schema = {
name: {
type: 'string',
title: 'User Name', // 输入框对应的 label,不提供的话默认使用 key 值
description: 'input text for user name', // 该字段的描述,显示在输入框下方
default: 'bob', // 该字段的默认值
options: {
// 可以通过 options 字段传入一些定制化的设定
inputAttributes: {
placeholder: 'your name here...',
class: 'form-control'
}
}
}
};string 提供了一个属性 minLength 用于限制字符串的最小长度。
let schema = {
type: 'string',
// 相当于限制该字符串不能为空
minLength: 1
};textarea
当 format 为 textarea 时,渲染为文本域形式,可以支持输入大段文字。
let schema = {
type: 'string',
format: 'textarea'
};colorpicker
当 format 为 color 时,渲染为颜色选择器形式,可以支持输入色值。
通过 options 中设置 colorpicker 为一个对象值,可以定义颜色选择器的细节。
let schema = {
type: 'string',
format: 'color',
options: {
colorpicker: {
popup: 'bottom', // 弹出位置,支持 top、left、right,默认是 bottom
editorFormat: 'hex', // 颜色格式,支持 rgb、hsl,默认是 hex
alpha: true // 是否支持透明度
}
}
};datetime
当需要输入日期或时间类的字符串值时,可以使用 format 来指定相应的格式。
编辑器共提供了 3 种类型:
- date,渲染为日期选择框,返回值为 ‘YYYY-MM-DD’ 格式
- time,渲染为时间选择框,返回值为 ‘HH:MM’ 格式
- datetime-local,渲染为日期+时间选择框,返回值为 ‘YYYY-MM-DD HH:MM’ 格式
通过 options 中设置 flatpickr 为一个对象值,可以使用第三方控件 flatpickr,并支持传入其原生配置。
let schema = {
type: 'string',
format: 'datetime-local',
options: {
flatpickr: {
inline: true, // 是否启用行内模式,即日期选择框直接显示,和 wrap 互斥
inlineHideInput: false, // 当启用 inline 模式时,是否隐藏原生的输入框
wrap: true, // 是否启用按钮群组模式,可以显示切换和清除按钮,和 inline 互斥
showToggleButton: false, // 当启用 wrap 模式时,是否显示切换按钮
showClearButton: false, // 当启用 wrap 模式时,是否显示清除按钮
defaultHour: 7, // 默认小时数
defaultMinute: 19, // 默认分钟数
hourIncrement: 2, // 每次点击按钮小时增量
minuteIncrement: 3, // 每次点击按钮分钟增量
enableSeconds: true, // 是否启用秒数
time_24hr: true, // 是否启用 24 小时制
allowInput: true // 是否允许手动输入
}
}
};uuid
当 format 为 uuid 时,渲染为一个只读的输入框,自动生成 uuid 格式字符串。
let schema = {
type: 'string',
format: 'uuid',
description: 'uuid field with value'
};upload
编辑器内置了一个上传控件,可以支持相关文件的上传。
启用方法:
- 首先设置
format为 _url_,同时通过options中设置 upload 的相关属性,即可启用一个带文件预览和上传进度的上传控件。 - 在相关属性内,使用
upload_handler字段可以指定一个上传的处理函数名。 - 同时要通过
JSONEditor.defaults.callbacks.upload属性实现该上传处理函数。该函数有四个回调参数 jseditor, type, file, callback。- jseditor:当前编辑器实例
- type:上传控件对应的路径字段
- file:上传控件选中的文件
- callback:回调对象(提供了 success、failure、updateProgress 方法)
- success:成功的回调方法,用于给控件对应的字段赋值
- failure:失败的回调方法,用于控件显示错误提示信息
- updateProgress:上传进度的回调方法,用于控件实时渲染进度提示
- 可以通过
links字段设置上传成功后的回显:默认是显示文件完整路径,可以用rel:view来仅显示 view 字样的链接
let schema = {
type: 'string',
format: 'url',
options: {
upload: {
upload_handler: 'uploadHandler'
}
},
links: [
{
href: '{{self}}',
rel: 'view'
}
]
};
JSONEditor.defaults.callbacks.upload = {
uploadHandler: function (jseditor, type, file, callback) {
if (type === 'root.uploadfail') {
callback.failure('Upload failed');
} else {
var step = 0;
var tickFunction = function () {
step += 1;
console.log('progress: ' + step);
if (step < 100) {
callback.updateProgress(step);
window.setTimeout(tickFunction, 50);
} else if (step == 100) {
callback.updateProgress();
window.setTimeout(tickFunction, 500);
} else {
callback.success('http://www.example.com/images/' + file.name);
}
};
window.setTimeout(tickFunction);
}
}
};base64
针对小型文件的录入,可以不使用 upload 控件,而用 base64 的方式,直接将文件内容嵌入字段中。
我们只需要设置 media.binaryEncoding 为 base64 即可。这时字段会渲染为文件控件,但是不带上传功能,所选中的文件内容会编码为 base64 格式,并随着整体 JSON 数据一起提交。
let schema = {
type: 'string',
media: {
binaryEncoding: 'base64',
type: 'img/png'
}
};hidden
对于不需要在界面显示和编辑的隐藏值,可以使用 hidden 类型来解决。
hidden 控件实现有两种方法:
- 通过
options.hidden属性设置为 true 实现,整个字段不再显示,但是最终 JSON 值包含该字段值 - 通过
format设置为 hidden 实现,输入控件不再显示,但是字段标题 label 还会渲染
let schema = {
hidden: {
type: 'string',
options: {
hidden: true
}
},
hiddenAnother: {
type: 'string',
format: 'hidden'
}
};SCEditor
SCEditor 提供基于 HTML 和 BBCode 格式的所见即所得(WYSIWYG)的编辑体验。启用它也很简单:format 设置为 xhtml 或 bbcode ,然后 options 中设置 wysiwyg 为 true 即可。
let schema = {
type: 'string',
format: 'xhtml',
options: {
wysiwyg: true
}
};SimpleMDE
SimpleMDE 是一个提供动态预览的简单 Markdown 编辑器。format 设置为 markdown 即可启用。
let schema = {
type: 'string',
format: 'markdown'
};Ace Editor
Ace Editor 是一个支持语法高亮的源代码编辑器,支持如下格式,format 设置为对应值即可启用相应语法高亮和检查。
- c
- cpp (alias for c++)
- csharp
- css
- less
- sass
- scss
- dart
- golang
- html
- ini
- java
- javascript
- json
- lua
- makefile
- php
- python
- ruby
- sql
- pgsql
- mysql
- xml
- yaml
同时 还能通过 options.ace 传入 Ace Editor 的原生支持选项
let schema = {
type: 'string',
format: 'sql',
options: {
ace: {
theme: 'ace/theme/vibrant_ink',
tabSize: 2,
wrap: true
}
}
};结合 enum 属性
当通过 enum 属性提供了可选枚举值后,string 字段会被渲染为下拉选择框。假如设置 format 为 _radio_,就可以切换为单选框形式(推荐在可选项小于 5 个时使用)。
let schema = {
type: 'string',
format: 'radio',
enum: ['get', 'post', 'put', 'delete']
};注:当为 radio 时,该字段默认为 required
另外编辑器也引入了 select2 第三方控件用于优化选择效果,同样的,设置 format 为 _select2_,就可以启用。
let schema = {
type: 'string',
format: 'select2',
enum: ['get', 'post', 'put', 'delete']
};boolean
boolean 类型默认是下拉选择框形式,内置选项 true 和 false。假如设置 format 为 _checkbox_,就可以切换为复选框形式。
let schema = {
type: 'boolean',
format: 'checkbox',
title: '是否启用',
default: true
};另外 Press 还新增了一个切换开关形式用于布尔类型。
let schema = {
type: 'boolean',
format: 'toggle'
};number 和 integer
number、integer 类型都是用于输入数字值,它们的唯一区别就是一个接受数字,一个接受整数,默认是输入框。
另外可以通过 maximum 和 minimum 属性限定最大最小值。
integer 类型可设置 format 为 _range_,切换为滑块形式;_rating_,切换为打星评分形式(默认 minimum: 1,另外可以设置属性 exclusiveMaximum,表示可取值范围不包括最大值)。
let schema = {
type: 'integer',
default: 1,
minimum: 1,
maximum: 1000
};datetime
datetime 控件也支持数值类型,同 string 下 datetime 类似,只是返回值为对应的时间戳。
let schema = {
type: 'number',
format: 'datetime-local',
options: {
flatpickr: {
...
}
}
};结合 enum 属性
当通过 enum 属性提供了可选枚举值后,number 字段会被渲染为下拉选择框。假如设置 format 为 _radio_,就可以切换为单选框形式(推荐在可选项小于 5 个时使用)。
let schema = {
type: 'integer',
enum: [1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014]
};array
array 作为 JSON 数据的重要组成类型,相应的,数组编辑区也占据了编辑器的大量篇幅(包括界面、代码等等)。 除了默认形式,另外还提供了 table 和 tabs 两种 format 形式来编辑数组。
- 默认: 数组元素从上到下,垂直排列分布,适合元素数量少时。
- table: 用表格的形式展示数组元素,适合元素数量多且元素为对象且属性少的情况。
- tabs: 用左页签来切换数据元素,永远只显示一个元素,适合元素为对象且属性多的情况。
- tabs-top: 同上,只是改为顶页签。
let schema = {
type: 'array',
items: {
type: 'string'
}
};
let schema2 = {
type: 'array',
format: 'table',
items: {
type: 'object',
properties: {
name: {
type: 'string',
options: {
// 通过 input_width 变相实现自定义 td 的宽度
input_width: '60px'
}
},
id: {
type: 'string'
}
}
}
};array 类型提供了一个 uniqueItems 属性,当为 true 时,可以避免添加重复项。Press 针对该属性做了优化,可以通过传入字符串来指定数组元素的某个属性不能重复。
let schema = {
type: 'array',
format: 'table',
uniqueItems: 'name',
items: {
type: 'object',
properties: {
name: {
type: 'string'
},
id: {
type: 'string'
}
}
}
};array 类型提供了两个属性用于限制数组的长度 minItems 和 maxItems
let schema = {
type: 'array',
format: 'table',
uniqueItems: true,
minItems: 1,
maxItems: 10,
items: {
type: 'string'
}
};结合 enum 属性
同样的,通过 enum 属性提供了可选枚举值并同时设置 uniqueItems 属性后,array 字段会被渲染为多选形式。假如可选项小于 8 个时会被渲染为复选框样式,否则渲染为下拉多选样式。可以通过设置 format 为 select 或 _checkbox_,进行显式定义。
let schema = {
type: 'array',
format: 'checkbox',
uniqueItems: true,
items: {
type: 'string',
enum: ['A-Yes', 'A-Unknown', 'B-Yes', 'B-Unknown', 'C-Yes', 'C-Unknown', 'D-Yes', 'D-Unknown', 'E-Yes', 'E-Unknown']
}
};上文提及的 select2 也支持多选,设置 format 为 _select2_,就可以启用。
let schema = {
type: 'array',
format: 'select2',
uniqueItems: true,
items: {
type: 'string',
enum: ['A-Yes', 'A-Unknown', 'B-Yes', 'B-Unknown', 'C-Yes', 'C-Unknown', 'D-Yes', 'D-Unknown', 'E-Yes', 'E-Unknown']
}
};array 事件
编辑器针对 array 的元素常见操作(增加、删除、移动)都提供了对应的钩子函数便于做相应的处理。
editor.on('moveRow', (editor) => {
console.log('moveRow', editor);
});
editor.on('addRow', (editor) => {
console.log('addRow', editor);
});
editor.on('deleteRow', (editor) => {
console.log('deleteRow', editor);
});
editor.on('deleteAllRows', (editor) => {
console.log('deleteAllRows', editor);
});object
object 编辑区也是编辑器的重要组成部分之一。该编辑区除了默认布局也提供了其他布局用于精简界面。
- 默认: 每个子属性单独占据一行。
- grid: 多个子属性并排在一行显示,每个子属性可以通过 grid_columns 选项来设置宽度,然后 每行会尽可能占满 12 格后换行,所以该布局不能保证子属性的显示顺序和代码一致。
- grid-strict: 同上,但是每个子属性会严格按照 grid_columns 显示,不会自动扩展。同时支持通过 grid_break 选项来设置手动换行。
- categories: 通过顶页签形式对子属性进行分组,每个对象或数组属性对应一个页签(页签标题来自对象或数组的标题),剩余的其他属性为一个页签(标题默认为 Basic,可以通过 basicCategoryTitle 属性进行自定义)。
let schema = {
type: 'object',
properties: {
name: {type: 'string'}
}
};let schema = {
type: 'object',
format: 'grid-strict',
properties: {
a: {
title: 'a',
type: 'string',
options: {
grid_columns: 4
}
},
b: {
title: 'b',
type: 'string',
options: {
grid_columns: 4,
grid_break: true
}
},
c: {
title: 'c',
type: 'string',
options: {
grid_columns: 6
}
},
d: {
title: 'd',
type: 'string',
options: {
grid_columns: 6
}
}
}
};let schema = {
type: 'object',
format: 'categories',
basicCategoryTitle: 'ab',
properties: {
a: {
title: 'a',
type: 'string'
},
b: {
title: 'b',
type: 'string'
},
location: {
type: 'object',
title: 'Location',
properties: {
city: {
type: 'string'
},
state: {
type: 'string'
}
}
},
people: {
type: 'array',
format: 'table',
title: 'People',
uniqueItems: true,
items: {
type: 'string'
}
}
}
};button
默认为 required