TLDR
- All user interfaces in Lowdefy are assembled out of blocks.
Block types
- There a five block categories:
display
,input
,context
,container
andlist
. - Operators re-evaluate on every
state
update or as request calls complete. This allows blocks to live update. - Lowdefy has built in default block types, however this can be overwritten or extended with custom blocks by defining
types
on the Lowdefy config root. input
blocks maintain a value instate
matching the blockid
key. Dot notation applies to specify nested fields.
Block validation
- Field level input validation can be achieved by marking a
input
block asrequired
or by specifying a list ofvalidate
tests. - Validation is invoked using the
Validate
action.
Block events
- All blocks have
onMount
andonMountAsync
events. - Each block implements it's own additional events such as
onClick
etc.
Block loading
- By default all blocks render a loading skeleton when the block's source code is fetched or while the block is waiting on data from a request.
- A block's default loading can be overwritten by defining custom
loading
settings on a block.
A Lowdefy page is compiled out of an arrangement of blocks. Every HTML element of this page is render as a result of a block placed and configured on the page. Blocks make it simple for Lowdefy developers to create apps since they only have to decide what block type to use, where in the layout the block should render, and what the block should do by defining the block's properties
. How a block implements these properties
is up to the specific block type selected.
Lowdefy offers a list of over 30 block types to cater for a wide range of use cases. All blocks are categorized according to their primary function:
display
- Display page elements.input
- Modify a value instate
.context
- Create a newcontext
.container
- Render other blocks intocontent areas
.list
- Rendercontent areas
and blocks for each element in the data array.
When state
updates or a requests call completes, the Lowdefy engine reevaluates all operators and rerenders blocks for which the operator evaluation is different from the previous render result. The result is live updates to all blocks on a page. Operators can be used to build live update logic into all block fields, except for the id
, type
, areas
, blocks
and loading
fields.
Block Schema
The schema for a Lowdefy block is:
id: string
: Required - A unique identifier for a block. ForInput
blocks the blockid
sets the field key which the block will modify instate
. Field dot-notation can be used to express fields which are nested in objects or arrays.type: string
: Required - The is the block type identifier and defines what block to used. The block type used must either be a default block type or must defined in your app'stypes
configuration.properties: object
: All the settings passed to a block component. Operators are evaluated.areas: object
: Used to set the content areas and content layout settings forcontainer
,context
andlist
blocks. See layout for more details on how to useareas
.blocks: array
: A array of blocks to render to the defaultcontent
area forcontainer
,context
andlist
blocks. See layout for more details on how to use theblocks
array.events: object
: Used to definedactions
that run when the block triggers anevent
.layout: object
: Used to define the layout properties for a block. Operators are evaluated.loading: object
: Used to overwrite a block's default loading behavior.required: boolean | string
: Forinput
blocks, whether or not a value value is required instate
when theValidate
action is called. Can be either a boolean or a string that is used as the validation error message . Operators are evaluated.style: css object
: Used to apply css style settings to the block's top leveldiv
element. Operators are evaluated.validate: array
: A list of validation tests to pass when theValidate
action is called. Operators are evaluated.visible: boolean
: Controls whether or not to render a block. Operators are generally used here, and must evaluate tofalse
to make the block invisible. Blocks withvisible: false
are excluded fromstate
. Operators are evaluated.
Block types
Lowdefy has list of default block types as defined in the Lowdefy docs. The default Lowdefy blocks aim to cover a very generic implementation of the Ant Design react component library. To use all the default block types, you can simply use the block type
key, like Button
, TextInput
, or Box
.
Default block type config example:
lowdefy: LOWDEFY_VERSION
pages:
- id: example_dashboard
type: PageHeaderMenu
blocks:
- id: basic_chart
type: Button
properties:
# ... Button details
However, the default types can overwritten or additional types can be define as required. For example, to set a type
for a custom implementation of AmCharts, we can do the following. We have created a custom Lowdefy block for AmCharts v4 that we can use.
Custom block type config example:
lowdefy: LOWDEFY_VERSION
types:
AmChartsXY:
url: https://blocks-cdn.lowdefy.com/v3.10.1/blocks-amcharts/meta/AmChartsXY.json
pages:
- id: example_dashboard
type: Context
blocks:
- id: basic_chart
type: AmChartsXY
properties:
# ... AmCharts details
More details on custom blocks can be found here.
Input block validation
All input
block types maintain a value in state
. This value is set to the field name matching the block id
. Nested fields can be created by using dot notation in the id
to specify the field path.
Client side field validation can be applied setting the required
and / or validate
block fields. The following schema applies to required
and validate
.
Field validation is first evaluated when the Validate
action is invoked on a page.
required
schema:
required
can be a boolean
or string
type. When required: true
the field label will indicate this with a red dot for user feedback, and a value will have to be supplied in to the field in order to pass validation. If required
is set to a string
, this string will be used as the feedback message when the validation fails.
- id: name
type: TextInput
required: Please provide your name.
properties:
title: Name
validate
schema:
The validate
field takes a array
of test objects
to evaluate before passing the field validation. This list of tests are evaluated sequentially, so the test that fails first will be used as the feedback message to the user.
The schema for the validation test objects
:
pass: boolean
: Required - The test that validates if this item passes or not. This is usually written as operators which evaluates to atrue
orfalse
. Operators are evaluated.message: string
: Required - The feedback message to the user if this validation tests fails. Operators are evaluated.status: enum
: The feedback type to present to the user. Option areerror
andwarning
. Default iserror
. Operators are evaluated.
The following validate
example first verifies that something was entered into the email
field, then checks that the field passes a email regex validation using the _regex
operator:
- id: email
type: TextInput
validate:
- message: Please enter a email address.
status: error
pass:
_not:
_not:
_state: email
- message: Please provide a valid email address.
status: error
pass:
_regex: '^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'
properties:
title: Email
Block events
By default all blocks implements onMount
and onMountAsync
events. Both the onMount
and onMountAsync
events are triggered when the block is mounted. For the onMount
event, the block only mounts when the event action chain is completed, however, for the onMountAsync
event, the block will mount as soon as possible while the event actions completes execution.
Apart from the onMount
and onMountAsync
events, most blocks also implements their own block specific events such as onOpen
for Modal or onClick
for Button. See the events tab on each block's documentation for more details.
See the events and actions page for more details.
Block loading
Block loading renders a placeholder block while the block component is being fetched, or a block is waiting on a request to return before to rendering the block. This allows for a smoother user experience and reduces 'bounce' in the user interface as more blocks takes up their full width and height on the page while in a loading state.
By default, Lowdefy tries to give a reasonable definition for how much space a block should take up in while loading, however this can vary depending on how the block is used. The loading
property on blocks allows the Lowdefy developer to set a custom loading configuration for a block.
Custom block loading
example:
pages:
- id: page_one
type: Context
blocks:
# ...
- id: paragraph_one
type: Title
loading:
type: SkeletonParagraph
properties:
lines: 1
properties:
content: Lorem ipsum dolor sit amet.
# ...
Loading placeholder types
The following loading placeholder types are available:
Spinner
A Lowdefy logo loading spinner placed at the center of the block. Often used as the full page loading spinner logo. The following properties
apply to Spinner
:
barColor: string
: Color of the bars in the Lowdefy spinner logo.color: string
: Color of spinner logo. Default is#f1f1f1
.height: number | string
: Height of the spinner block including background. Default is100%
.shaded: boolean
: Masks the spinner block including background.size: number | string
: Size of the spinner icon. Default is50px
.
IconSpinner
A spinning loading icon. The following properties
apply to IconSpinner
:
size: number | enum
: Size of the spinner icon. Options aresmall
,medium
andlarge
. Default is20px
.
Skeleton
A rectangular loading skeleton to fill the full size of the block. The following properties
apply to Skeleton
:
height: number | string
: Height of the skeleton block. Default is100%
.width: number | string
: Width of the skeleton block. Default is100%
.
SkeletonAvatar
A avatar loading skeleton. The following properties
apply to SkeletonAvatar
:
size: number | enum
: Size of the avatar skeleton. Options aresmall
,medium
andlarge
. Default is32px
.shape: enum
: Shape of the avatar skeleton. Options aresquare
andround
. Default isround
.
SkeletonButton
A button loading skeleton, matches the size of Button
blocks. The following properties
apply to SkeletonButton
:
size: enum
: Size of the button skeleton. Options aresmall
,medium
andlarge
. Default ismedium
.shape: enum
: Shape of the button skeleton corners. Options aresquare
andround
. Default isround
.height: number | string
: Height of the button skeleton. Overwrites the size setting.width: number | string
: Width of the button skeleton. Default is100%
.
SkeletonInput
A input loading skeleton, used as a placeholder for input blocks with labels. The following properties
apply to SkeletonInput
:
size: enum
: Size of the input skeleton. Options aresmall
,medium
andlarge
. Default ismedium
.labelHeight: number | string
: Height of the label part of the input skeleton.inputHeight: number | string
: Height of the input part of the input skeleton. Overwrites the size setting.labelWidth: number | string
: Width of the label part of the input skeleton. Default is100%
.width: number | string
: Width of the input part of input skeleton. Default is100%
.
SkeletonParagraph
A paragraph loading skeleton, used as a placeholder for text intensive section. The following properties
apply to SkeletonParagraph
:
lines: number
: The number of paragraph lines to render. Default is4
.width: number | string
: Width of the paragraph skeleton. Default is100%
.