Formify Language¶
This chapter gives an overview of formify’s language.
Application¶
The App is the root of every formify file. It can contain a Data Model and a View Model. It also has a unique name. The most simple form of an app with a data model and a view model looks like this:
app MyApp {
model {}
view {}
}
Data Model¶
The data model contains all the entities and custom data types of your app. A data model with a single Entity looks like this:
Entity¶
TBD
model {
entity Person {}
}
Property¶
Each Entity can contain a list of properties. A property declaration starts with the optional keyword prop, a unique name, followed by a colon and a Type. The code generator uses this data type to decide which kind of control to generate. The most basic property declaration looks like this:
entity Person {
prop firstname : string
}
Constraints¶
There is also the option to add constraints to a Property. This information is used by the generator to add specific form validation to the controls. The following shows an example with some predefined constraints:
entity Person {
firstname : string required
email : string email required
age : number min(18)
}
The list of available constraints depends on the Type. Currently, the following constraints are built in:
string
required() : marks this field as required
lowercase() : only allows strings written in lowercase
uppercase() : only allows strings written in uppercase
min(limit : number) : defines the minimum length of the string
max(limit : number) : defines the maximum length of the string
length(length : number) : defines the exact length of the string
email() : built-in regular expression check for email
url() : built-in regular expression check for urls
number
min(limit : number) : defines the minimum value of the number
max(limit : number) : defines the maximum value of the number
positive() : only allows positive numbers
negative() : only allows negative numbers
lessThan(max : number) : only allow values that are less than the specificed value
moreThan(max : number) : only allow values that are more than the specificed value
date
min(limit : number) : defines the minimum value of the date
max(limit : number) : defines the maximum value of the date
array
min(limit : number) : defines the minimum length of the array
max(limit : number) : defines the maximum length of the array
length(length : number) : defines the exact length of the array
Type¶
formify’s type system provides to following primitive types:
string
number
boolean
date
time
image
color
Those types can be used as property types, like this:
entity Pet {
prop name : string
}
entity Person {
prop firstname : string
prop age: number
prop adult : boolean
prop birthday : date
prop photo : image
prop favColor : color
prop pets : array<Pet>
}
Relationships¶
Entities may have relationships to other entities. A one-to-one relationship can be specified by using an Entity as a type within a property declaration like shown in this example:
entity Person {
address : Address
}
entity Address {
street : string
city : string
}
Many-to-One relationships can be specified with the use of an array:
entity Student {
courses : array<Course>
}
entity Course {
name : string
}
Inheritence¶
Formify supports inheritance with the extends
keyword. Entity can extend other entities to reuse fields.
Multi-inheritence is also possible.
entity Person {
firstname : string
lastname : string
}
entity Student extends Person {
studentId : number
}
entity Professor extends Person {
professorId : number
}
Enumeration¶
You can add Enumerations with the enum keyword like this:
enum Gender {MALE, FEMALE}
entity Person {
gender : Gender
firstname : string
lastname : string
}
View Model¶
Formify provides a view model that you can use to define different view components. Currently supported types are Form, Composite, Tabs, Wizard, Collection and Master - Detail.
A simple application with a view model that contains a Form looks like this:
app PersonManagement {
model {
entity Person {
firstname : string
lastname : string
}
}
view {
@Root
form PersonDetails {
entity Person
}
}
}
Note
The Form is annotated with the @Root
annotation. This is used by formify as a pointer to the root component of the application.
If no view component is annotated with @Root
you will get a rendering error. If multiple components are annotated with @Root
, they will be added to the application bar.
Form¶
The most simple form declaration only consists of a reference to the underlying Entity. If no form fields are defined, this is simply a shortcut that implicitly uses all Property of the Entity.
form PersonDetails {
entity Person
}
If you do not want to display all the entities properties or want to fine-tune the form controls, you can explicitly define
the form fields with the field
keyword like shown in this example:
app PersonManagement {
model {
entity Person {
firstname : string
lastname : string
secretKey : string
}
}
view {
@Root
form PersonDetails {
entity Person
field FirstName : firstname
field LastName : lastname
}
}
}
Note
You can navigate the Relationships with the .
- operator:
For example, if an Entity Person
has a one-to-one Relationships to another Entity Address
,
you can reference the city in the form field with address.city
:
app PersonManagement {
model {
entity Person {
address : Address
}
entity Address {
city : string
}
}
view {
form AddressDetails {
entity Person
field city : address.city
}
}
}
Composite¶
Components are a great concept to split up a Form into different, reusable parts. Imagine having an Entity with a lot of properties, it might make sense to group some properties into a single Form. With Composites, you can group these Forms together to one composite form like this:
app PersonManagement {
model {
entity Person {
firstname : string required
lastname : string
city: string
address : string
}
}
view {
@Root
composite CompositePerson {
entity Person
parts
PersonDetail,
AddressDetails
}
form AddressDetails {
entity Person
field City : city
field Address : address
}
form PersonDetail {
entity Person
field FirstName : firstname
field LastName : lastname
}
}
}
Composites also play together nicely with one-to-one Relationships. Like shown in this example, you can pass a reference to the AddressDetails part using the
value
keyword:
app PersonManagement {
model {
entity Person {
firstname : string required
address : Address
}
entity Address {
city : string
street : string
}
}
view {
@Root
composite CompositePerson {
entity Person
parts
PersonDetails,
AddressDetails value address
}
form AddressDetails {
entity Address
}
form PersonDetails {
entity Person
}
}
}
Tabs¶
Tabs are a special kind of Composite. Each part is displayed in a seperate Tab.
app PersonManagement {
model {
entity Person {
firstname : string required
lastname : string
city: string
address : string
}
}
view {
@Root
tab-composite CompositePerson {
entity Person
parts
PersonDetail,
AddressDetails
}
form AddressDetails {
entity Person
field City : city
field Address : address
}
form PersonDetail {
entity Person
field FirstName : firstname
field LastName : lastname
}
}
}
Wizard¶
A Wizard is also a special kind of Composite. Each part is displayed as a seperate step in a multi step wizard.
app PersonManagement {
model {
entity Person {
firstname : string required
lastname : string
city: string
address : string
}
}
view {
@Root
wizard CompositePerson {
entity Person
parts
PersonDetail,
AddressDetails
}
form AddressDetails {
entity Person
field City : city
field Address : address
}
form PersonDetail {
entity Person
field FirstName : firstname
field LastName : lastname
}
}
}
Collection¶
A collection shows a list of entities.
app PersonManagement {
model {
entity Person {
firstname : string
lastname : string
city: string
address : string
}
}
view {
@Root
collection PersonCollection {
entity Person
field name : firstname
field lastname : lastname
}
}
}
Grid¶
A Grid is a special type of collection. A Grid shows a collection of entities with different columns. The Grid can be configured with @Pagesize and @Sortable Annotations
app PersonManagement {
model {
entity Person {
firstname : string
lastname : string
city: string
address : string
}
}
view {
@Root
@Pagesize(pageSize = 5)
@Sortable
grid PersonCollection {
entity Person
field name : firstname
field lastname : lastname
field city : city
}
}
}
Master - Detail¶
A maaster detail is a combination of a Collection for the master part and a form for the detail part.
app PersonManagement {
model {
entity Person {
firstname : string
lastname : string
city: string
address : string
}
}
view {
@Root
@Alignment(Align.Horizontal)
master-detail Application {
entity Person
master PersonCollection
detail PersonDetails
}
collection PersonCollection {
entity Person
field name : firstname
}
form PersonDetails {
entity Person
field name : lastname
field lastname : lastname
field city : city
}
}
}