社内勉強会用資料。社内ツールでJSON Schemaとreact-jsonschema-formを利用しているので、それについての紹介です。
JSON Schema
JSONの構造を定義するJSON。
例えば、下記のようなユーザを表すJSONがあるとする。
{
"id": "00000000-0000-0000-0000-000000000001",
"name": "Taro YAMADA",
"age": 30
}
-
id
はUUIDで、必須項目 -
name
は英字のみで、必須項目 -
age
は0以上の整数で、任意項目
こういう条件だった場合、JSON Schemaで下記のように定義できる。(あくまで一例だけど)
{
"title": "ユーザー",
"type": "object",
"properties": {
"id": {
"title": "ID",
"type": "string",
"pattern": "^[0-9a-zA-Z]{8}(-[0-9a-zA-Z]{4}){3}-[0-9a-zA-Z]{12}$"
},
"name": {
"title": "ユーザー名",
"type": "string",
"pattern": "^[\\sa-zA-Z]+$"
},
"age": {
"title": "年齢",
"type": "integer",
"minimum": 0
}
},
"required": [ "id", "name" ]
}
他にも色々と出来るけど、今回は割愛します。一番最初に貼ったリンクで仕様を読むか、下記のドキュメントが分かりやすかったので、そちらで勉強してください。
Understanding JSON Schema — Understanding JSON Schema 1.0 documentation
react-jsonschema-form
mozilla-services/react-jsonschema-form: A React component for building Web forms from JSONSchema.
react-json-schema-formは、JSON Schemaからフォームを生成してくれるReact Component。
Github Pagesにデモページがあるので、試しに先程のJSON Schemaを入れてみると下記のようなフォームが生成される。
使い方
Formコンポーネントに、下記のようなpropsを渡せば、最低限動作する。その他のpropsについては後述する。
-
schema
... JSON Schema -
formData
... JSON -
onChange
... 変更された時に呼ばれるハンドラ -
onSubmit
... Submitボタンを押した時に呼ばれるハンドラ
import React from 'react';
import ReactDOM from 'react-dom';
import Form from 'react-jsonschema-form';
const schema = { ... };
const formData = {};
function handleChange({ formData }) {
// 入力されたデータ
console.log(formData);
}
function handleSubmit({ formData }) {
// 入力されたデータ
console.log(formData);
}
ReactDOM.render(
<Form
schema={schema}
formData={formData}
onChange={handleChange}
onSubmit={handleSubmit}
/>,
document.getElementById('app')
);
カスタマイズ
react-jsonschema-formは、カスタマイズがしやすいのが魅力だと思う。カスタマイズ方法を軽く紹介する。
uiSchema
propsにuiSchema
を渡すと、UI周りのカスタマイズが可能。
- フィールド名、placeholderなどの変更
- デフォルトの
<input>
要素の変更 - class属性の変更
などなど、いろいろできる。わかりやすいやつを一部を紹介。
例1)helpTextの追加
<Form
schema={{ ...さっきのJSON Schema }}
uiSchema={{
"name": {
"ui:help": "半角英字、スペースのみ"
}
}}
/>
こうすると、
こうなる。
例2)placeholder
<Form
schema={{ ...さっきのJSON Schema }}
uiSchema={{
"name": {
"ui:placeholder": "半角英字、スペースのみ"
}
}}
/>
こうすると、
こうなる。(エラー起きちゃってるけど)
カスタムField
例えば、JSON Schema上は文字列でURLだが、ファイルアップロードするUIを表示したい場合、独自のFiledを表示することができる。
// JSON的にはURLが欲しい
const schema = {
type: "string",
format: "uri"
};
// AssetFieldコンポーネントを`asset`という名前で登録する
const customFields = {
asset: AssetField,
};
// FieldにAssetFieldコンポーネントを使う
const uiSchema = {
'ui:field': 'asset'
};
// fieldsに渡す
<Form schema={schema} uiSchema={uiSchema} fields={customFields} />
AssetFieldでは、下記のようにpropsで渡ってくるonChangeに値を渡して上げればOK。
import React, { Component, PropTypes } from 'react';
import uploadFile from './uploadFile';
class AssetField extends Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
// ファイルをサーバにアップロードして
// URLを取得するような関数
uploadFile(e.target.files[0]).then(url => {
// onChangeで上げる値は、
// JSON Schema通りの値じゃないと
// validationでエラーになってしまう
this.props.onChange(url);
});
}
render() {
const { required, disabled } = this.props;
// ファイルアップロードを表示
return (
<input
type="file"
className="form-control"
required={required}
disabled={disabled}
onChange={this.handleChange}
/>
);
}
}
export default AssetField;
おわり
とりあえず、こういうのあるよという紹介。JSON Schemaもreact-jsonschema-formももっと紹介したい機能があるので、またノウハウを貯めて書きたい