import _ from "lodash";
/**
* 特定のコンポーネントもしくは HTML タグを利用した uiSchema をまとめて生成するクラス
* @copyright yokra9
* @license MIT
*/
class UiSchemaGenerator {
/**
* @constructor
* @param {Object} jsonSchema JSON Schema の スキーマ定義部分
* @property {Object} uiSchema uiSchema
* @property {Object} schema JSON Schema の スキーマ定義部分
* @property {Object} fieldOptions デフォルトのデータオブジェクト
* @property {Object} errorOptions デフォルトのエラーオプション
* @see <a href="https://json-schema.org/">JSON Schema</a>
* @see <a href="https://jarvelov.gitbook.io/vue-form-json-schema/api/vue-form-json-schema/ui-schema">uiSchema</a>
*/
constructor(jsonSchema) {
this.uiSchema = new Array();
this.fieldOptions = {};
this.errorOptions = {};
if (jsonSchema) {
this.schema = jsonSchema;
} else {
throw new TypeError("スキーマ定義がありません");
}
}
/**
* デフォルトのデータオブジェクトを追加設定する。
* @param {Object} fieldOptions データオブジェクト
* @returns {UiSchemaGenerator} UiSchemaGenerator
*/
setDefaultFieldOptions(fieldOptions) {
// 再帰的マージ(Object.assign()は浅いマージ)
this.fieldOptions = _.merge(this.fieldOptions, fieldOptions);
return this;
}
/**
* デフォルトのエラーオプションを追加設定する。
* @param {Object} errorOptions データオブジェクト
* @returns {UiSchemaGenerator} UiSchemaGenerator
*/
setDefaultErrorOptions(errorOptions) {
// 再帰的マージ(Object.assign()は浅いマージ)
this.errorOptions = _.merge(this.errorOptions, errorOptions);
return this;
}
/**
* uiSchema を返却する
* @returns {Array} uiSchema
*/
toArray() {
return this.uiSchema;
}
/**
* 特定の要素の uiSchema をまとめて生成する
* @param {Object|String} component 生成するコンポーネントもしくはHTMLタグ名
* @param {Array<String>} [models] 要素と紐付けるモデル
* @param {Object} [fieldOptions] テンプレート内で使う属性に対応するデータオブジェクト。値として function(model, index) を取ることもできる。 {@link https://vuejs.org/v2/guide/render-function.html#The-Data-Object-In-Depth 公式の説明はこちら}
* @param {Object} [displayOptions] 表示するかどうかの条件を JSON Schema で指定する
* @param {Object} [errorOptions] エラーが発生した時のみ有効になる fieldOptions
* @param {Array} [children] 子要素
* @param {boolean} [errorHandler] エラーハンドリングを行うかどうか
* @returns {UiSchemaGenerator} UiSchemaGenerator
*/
generate(
component,
models,
fieldOptions,
children,
displayOptions,
errorOptions,
errorHandler
) {
if (!component) throw new TypeError("引数 component は必須です");
// モデルが未指定、もしくは空配列のとき
if (models == null || models.length == 0) {
this.uiSchema.push(
// uiSchema
{
component,
fieldOptions: _.mergeWith(
{},
// ダイナミックなデフォルト値(setDefaultFieldOptions()で外部から設定可能)
this.fieldOptions,
// 引数
fieldOptions,
(obj, src) => {
// modelsにはnull等が入る
if (typeof src == "function")
return src(models, this.uiSchema.length);
}
),
children,
displayOptions,
errorHandler,
errorOptions: _.merge({}, this.errorOptions, errorOptions),
}
);
} // モデルが一つ以上指定されているとき
else {
// 全モデルに対して uiSchema を生成する
models.forEach((model) => {
this.uiSchema.push(
// uiSchema
{
component,
model,
fieldOptions: _.mergeWith(
{},
// ダイナミックなデフォルト値(setDefaultFieldOptions()で外部から設定可能)
this.fieldOptions,
// 引数
fieldOptions,
(obj, src) => {
if (typeof src == "function")
return src(model, this.uiSchema.length);
}
),
children,
displayOptions,
errorHandler,
errorOptions: _.merge({}, this.errorOptions, errorOptions),
}
);
});
}
return this;
}
}
export default UiSchemaGenerator;