Schema

Prologue

JSON Schema is a specification to define JSON data structure, it doesn't include detailed explanation about how to convert the specification to specific forms, @delon/form is a dynamic form library developed based on our own understanding of JSON Schema and current data input components of ng-zorro-antd.

JSON Schema must always have a type type="object" as root node,therefore a simplest Schema structure at least is:

schema = {
  type: 'object', // optional, set to `object` by default
  properties: {}
}

Ahead of dscribing Schema, it is necessary to make a systematic description about the relationship between form elements and Schema.

As we know, form is a set of HTML elements, every element maps to one Schema property, a property has it's own data type, format, visual information, etc., but this is not enough to describe the rich APIs provided by ng-zorro-antd. In order to better use these APIs, @delon/form not only implemented most standard JSON Schema, but also added an additional property ui, which is used to describe how to render the property.

Non Pollution

Of course, you can set <sf [ui]="ui"> to add additional UI rendering if you have strict requirement about standard, or JSON Schema data is generated from backend. For example:

schema = {
  properties: {
    url: {
      type: 'string',
      title: 'Web Site'
    }
  }
}

A URL property, the pure JSON Schema structure cann't describe about adding prefix https://, but nz-input supports very rich prefix and postfix texts, so we can customize it in ui to add prefix https://:

ui = {
  $url: {
    addOnBefore: 'https://'
  }
}

ui itself is a JSON structure, in order to distinguish with relationship of JSON Schema property, must add prefix $ to all properties; must replace array elements with $items. When KEY is *, it is valid for all properties.

Relationship between Form and Data Structure

We think a complete form should include some of following elements:

Description from left to right:

Structure SourceParameterDescriptionTypeDefault Value
Schema[required]If requiredstring[]-
Schema[title]Titlestring-
ui[optional]Optional informationstring-
ui[optionalHelp]Optional help informationstring, SFOptionalHelp-
ui[placeholder]Placeholderstring-
Schema[description]Description for the propertystring-
-[error]Error informationstring-

Some Specifications

  • Following camelCase to name key

  • You can ignore description marked as Not recommended if you are very familiar with JSON Schema.

JSON Schema(SFSchema)

JSON Schema has complete specification descrbes for each property, @delon/form is currently based on specification draft-07, following is the detailed explanation of specification:

Common Type

ParameterDescriptionTypeDefault Value
[type]Data type, support JavaScript basic typesnumber,string,boolean,object,arrayobject
[enum]Enum, static data sourceSFSchemaEnumType[]-

Value Type

ParameterDescriptionTypeDefault Value
[minimum]Minimum valuenumber-
[exclusiveMinimum]If excluding minimum valueboolean-
[maximum]Maximum valuenumber-
[exclusiveMaximum]If excluding maximum valueboolean-
[multipleOf]Multiplenumber-

About exclusiveMinimum and exclusiveMaximum

The implementation mechanism of sf causes that it couldn't handle error capturing for type perpectly, therefore sf ignores all type (see config.ts) errors by default, these two kinds of errors are considered as type error, which will trigger invalid check. (find more details from #676

String Type

ParameterDescriptionTypeDefault Value
[maxLength]Maximum length of stringnumber-
[minLength]Minimum length of stringnumber-
[pattern]Regular expressionstring-

Array Type

ParameterDescriptionTypeDefault Value
[items]Array element description, only support array object. Can use other components if array of basic type is neededSFSchema-
[minItems]Minimum number of element in arraynumber-
[maxItems]Maximum number of element in arraynumber-
[uniqueItems]Element is unique in arrayboolean-
[additionalItems]additional validation rules for arraySFSchema-

Object Type

ParameterDescriptionTypeDefault Value
[maxProperties]Maximum number of property, must be a nonnegative integernumber-
[minProperties]Maximum number of property, must be a nonnegative integernumber-
[required]If requiredstring[]-
[properties]Propery definition{ [key: string]: SFSchema }-

Condition Type

ParameterDescriptionTypeDefault Value
[if]Condition validationSFSchema-
[then]Condition validationSFSchema-
[else]Condition validationSFSchema-

Validation of condition check is very strong and rich, but considering it breaks UI and adds complexity to component build, @delon/form only implements required, and uses it to determine if need validation, for example, a login page, it can show different login mode based on different login methods:

schema: SFSchema = {
  properties: {
    type: { type: 'string', enum: [ 'mobile', 'name' ], default: 'mobile' },
    name: { type: 'string' },
    pwd: { type: 'string' },
    mobile: { type: 'string' },
    code: { type: 'string' }
  },
  required: [ 'type' ],
  if: {
    properties: { type: { enum: [ 'mobile' ] } }
  },
  then: {
    required: [ 'mobile', 'code' ]
  },
  else: {
    required: [ 'name', 'pwd' ]
  }
};

For above configuraion, eventual behavior is showing mobile and code in UI when login method is mobile, otherwise, showing name and pwd.

Actually, condition type is eventually parsed to ui.visibleIf, Convert it to the following:

{
  properties: {
    login_type: {
      type: "string",
      title: "登录方式",
      enum: [
        { label: "手机", value: "mobile" },
        { label: "账密", value: "account" }
      ],
      default: "mobile",
      ui: {
        widget: "radio",
        styleType: "button"
      }
    },
    mobile: {
      type: "string",
      ui: {
        visibleIf: {
          login_type: val => val === "mobile"
        }
      }
    },
    code: {
      type: "number",
      ui: {
        visibleIf: {
          login_type: val => val === "mobile"
        }
      }
    },
    name: {
      type: "string",
      ui: {
        visibleIf: {
          login_type: val => val === "account"
        }
      }
    },
    pwd: {
      type: "string",
      ui: {
        type: "password",
        visibleIf: {
          login_type: val => val === "account"
        }
      }
    }
  },
  required: ["login_type"]
};

Logic Type

ParameterDescriptionTypeDefault Value
[allOf]Not recommended, can be replaced by requiredSFSchema[]-
[anyOf]Not recommended, can be replaced by required and minPropertiesSFSchema[]-
[oneOf]Not recommended, value must be one ofSFSchema[]-

Not recommended, mainly because there is no UI handle for logic type, it's similar to condition type, will affect UI rendering.

Format and Visual Type

ParameterDescriptionTypeDefault Value
[title]Titlestring-
[description]Descriptionstring-
[default]Default valueany-
[readOnly]If read only, equals to nzDisabledboolean-
[format]Data format, Docstring-

Other

ParameterDescriptionTypeDefault Value
[definitions]Internal definitionSFSchemaDefinition-
[$ref]Reference definitionstring-
[$comment]Comment for developer, no real meaning, won't be validatedstring-

Non Standard

ParameterDescriptionTypeDefault Value
[ui]UI configuration, has more priority than ui property of sf componentSFUISchemaItem-

UI(SFUISchemaItem)

UI Schema structure is composed by commonality and widgets, following is descriptioin of commonality part, please refer to widget API for widget part.

In order to keep integrity of API, Schema of widget may includes commonality information.

SFUISchema

Equals to <sf [ui]="ui">, a group of UI structure corresponds to JSON Schema structure, type is: [ key: string ]: SFUISchemaItem

Basic Type

ParameterDescriptionTypeDefault Value
[debug]Debug modeboolean-
[order]Order of propertystring[]-
[asyncData]Asynchronized static data source(input?: any) => Observable<SFSchemaEnumType[]>-
[hidden]Whether to hidebooleanfalse
[visibleIf]Is visible with conditions{ [key: string]: any[] | ((value: any, property: FormProperty) => boolean) }-
[visibleIfLogical]The logical used when specifying multiple visibleIfor, andor
[acl]ACL permission (Use can() verify)ACLCanType-

visibleIf

Is visible with conditions, for example:

  • visibleIf: { shown: [ true ] }: show current property when shown: true

  • visibleIf: { shown: [ '$ANY$' ] }: show current property when shown is any value

  • visibleIf: { shown: (value: any, property: FormProperty) => value > 0 }: complex expression

Validation Type

ParameterDescriptionTypeDefault Value
[liveValidate]If realtime validationbooleantrue
[firstVisual]If show visual error immediatelybooleanfalse
[onlyVisual]If only show visiual error not error textbooleanfalse
[ingoreKeywords]Ignore validation for some data typesstring[]
[errors]Customized error text{ [ key: string ]: string | ((obj: ErrorData) => string) }-
[showRequired]Whether to display the required logo *boolean-
[validator]Customized validator(value: any, formProperty: FormProperty, form: PropertyGroup) => ErrorData[]-

Array Type

ParameterDescriptionTypeDefault Value
[items]UI of specific sub elementSFUISchema-
[addTitle]Add TitlestringAdd
[addType]Add button style, equals to nzTypestringdashed
[removable]If show remove buttonboolean-
[removeTitle]Text of remove buttonstringRemove

Form Element Type

ParameterDescriptionTypeDefault Value
[type]type of inputstringtext
[placeholder]placeholderstring-
[autofocus]If auto focus during loadingboolean-

Render Type

ParameterDescriptionTypeDefault Value
[widget]Widgetstring-
[i18n]Refers to the i18n key of schema.titlestring-
[descriptionI18n]Refers to the i18n key of schema.descriptionstring-
[class]Customized class, equals to [ngClass]string,string[]-
[width]Width, unit: pxnumber-
[size]Size of elementdefault,large,small-
[grid]Property for responsiveSFGridSchema-
[optional]Optionalstring-
[optionalHelp]Optional helpstring, SFOptionalHelp-

Responsive Property SFGridSchema

grid equals to complete Grid, can determine how to render the form by grid

ParameterDescriptionTypeDefault Value
[gutter]Gutternumber-
[span]Number of column for each element, 0 means display: nonenumber-
[xs]<768px responsive grid, can be number of columns or including object of other propertiesnumber, SFGridSizeSchema-
[sm]≥768px responsive grid, can be number of columns or including object of other propertiesnumber, SFGridSizeSchema-
[md]≥992px responsive grid, can be number of columns or including object of other propertiesnumber, SFGridSizeSchema-
[lg]≥1200px responsive grid, can be number of columns or including object of other propertiesnumber, SFGridSizeSchema-
[xl]≥1600px responsive grid, can be number of columns or including object of other propertiesnumber, SFGridSizeSchema-
[xxl]Reserved field, support after version 0.7.0number, SFGridSizeSchema-

Horizontal Layout Type

The sum of label and control must be 24

ParameterDescriptionTypeDefault Value
[spanLabel]Number of column for labelnumber5
[spanControl]Number of column for form elementnumber19
[offsetControl]Number of column for left side of controlnumber-
[spanLabelFixed]Fixed width for labelnumber-