JFaster patterns: how do I…?
Common modeling tasks in the JFaster language, each with a complete, minimal answer. The full definitions are in the language specification.
How do I define an entity with required fields?
Customer @Sales order="name"
name d r
taxId r "Tax_ID"
email
phone
@Sales puts it in the Sales menu, d makes name its description, r marks required fields and order sets the default sort. email and phone get their types from their names.
How do I reference another entity?
Order @Sales order="orderDate desc"
customer Customer d r
orderDate date ds r default="now"
A PascalCase token after the name (Customer) makes the property a reference. Users choose a customer from a selector.
How do I make a master/detail form (an invoice with lines)?
Invoice @Billing order="issueDate desc"
customer Customer d r
issueDate date ds r default="now"
lines InvoiceLine set ei x childproperty="invoice"
total double ds calculated="sum(lines[*].amount)"
InvoiceLine @
invoice Invoice
product Product r
quantity integer r
unitPrice double r
amount double calculated="quantity * unitPrice"
set ei x edits the lines inline and lets users add rows; childproperty names the back-reference in the line. InvoiceLine @ has no menu entry because lines only exist inside an invoice.
How do I make cascading selectors (country → province → city)?
Province @Configuration order="name"
<subset name="forCountry" order="name">
<param name="country" entity="Country" />
<condition field="country" value="country" />
</subset>
name d r
country Country r
City @Configuration order="name"
<subset name="forProvince" order="name">
<param name="province" entity="Province" />
<condition field="province" value="province" />
</subset>
name d r
province Province r
Address @
country Country r
province Province r subset="forCountry" subsetparams="country"
city City r subset="forProvince" subsetparams="province"
Each selector is restricted to a parameterized subset, and subsetparams names the field that feeds it. When the country changes, the provinces are recomputed.
How do I restrict a selector to active records?
Supplier @Purchasing order="name"
<subset name="active" order="name">
<condition field="active" value="true" />
</subset>
name d r
active boolean default="true"
PurchaseOrder @Purchasing order="id desc"
supplier Supplier d r subset="active"
How do I add search filters to a listing?
Product @Catalog order="name"
<filter name="category" property="category" display="primary" />
<filter name="search" label="Search" display="primary">
<or>
<condition field="name" like="concat('%', search, '%')" />
<condition field="code" like="concat('%', search, '%')" />
</or>
</filter>
code d r
name d r
category Category
How do I split a listing into tabs by state?
<enumset name="TicketState">
<enum value="open">Open</enum>
<enum value="closed">Closed</enum>
</enumset>
Ticket @Support order="id desc" defaultlisting="main"
<subset name="open" order="id desc">
<condition field="state" value="'open'" />
</subset>
<subset name="closed" order="id desc">
<condition field="state" value="'closed'" />
</subset>
<listing name="main">
<tab name="open" label="Open" subset="open" displayactions="close" />
<tab name="closed" label="Closed" subset="closed" />
<tab name="all" label="All" />
</listing>
<action name="close" label="Close" type="relatedentity" entity="CloseTicket" location="local" defaultset="forTicket" />
subject d r
state enum enumset="TicketState" default="open" fixed
CloseTicket @ transient
<defaultset name="forTicket">
<param name="ticket" entity="Ticket" />
<default name="ticket" value="ticket" />
</defaultset>
ticket Ticket fixed
resolution text r
Each tab is a subset with its own actions. Strings in conditions go in single quotes ('open').
How do I model an operation (approve, send, import)?
With a transient entity: a form whose submission performs the operation. Open it with an action and prefill it with a defaultset.
Quote @Sales order="id desc"
<action name="send" label="Send to customer" type="relatedentity" entity="SendQuote" location="form" defaultset="forQuote" />
customer Customer d r
amount double ds r
SendQuote @ transient
<defaultset name="forQuote">
<param name="quote" entity="Quote" />
<default name="quote" value="quote" />
<default name="recipient" value="quote.customer.email" />
</defaultset>
quote Quote fixed
recipient email r
message text
What the operation does when submitted (sending the email) is business logic, written in the implementation's extension point for SendQuote.
How do I run an operation on many selected records?
Invoice @Billing order="id desc"
<action name="markPaid" label="Mark as paid" type="relatedentity" entity="MarkInvoicesPaid" location="listing" defaultset="forInvoices" />
number d r
paid boolean ds
MarkInvoicesPaid @ transient
<defaultset name="forInvoices">
<param name="invoices" entity="Invoice" collection="set" />
<default name="invoices" value="invoices" />
</defaultset>
invoices Invoice set fixed
paymentDate date r default="now"
location="listing" puts the action on the listing and passes the selected rows as a collection parameter.
How do I show related records inside a form?
Person @CRM order="lastName"
<subset name="forCompany" order="lastName">
<param name="company" entity="Company" />
<condition field="company" value="company" />
</subset>
<defaultset name="newForCompany">
<param name="company" entity="Company" />
<default name="company" value="company" />
</defaultset>
firstName d r / lastName d r
company Company r
Company @CRM order="name"
name d r
<embeddedlisting name="people" entity="Person" subset="forCompany" subsetparams="." defaultset="newForCompany" defaultsetparams="." />
People added from the company's form get the company prefilled.
How do I show a field only in some cases?
<enumset name="PaymentMethod">
<enum value="cash">Cash</enum>
<enum value="card">Card</enum>
<enum value="transfer">Bank transfer</enum>
</enumset>
Payment @Finance order="id desc"
method enum enumset="PaymentMethod" r
cardNumber displayif="method = 'card'"
bankAccount displayif="method = 'transfer'"
reference disabledif="method = 'cash'"
How do I compute a field?
From fields of the same form, use calculated:
OrderLine @
quantity integer r
unitPrice double r
discountPct double default="0"
amount double calculated="quantity * unitPrice * (1 - discountPct div 100)"
From other records, use a dynamic value:
OrderLine @
product Product r
unitPrice double disabled \
<dynamicvalue expr="product.price">
<param name="product" entity="Product" value="product" />
</dynamicvalue>
quantity integer r
From the database, for display in listings, use formula:
Company @CRM order="name"
name d r
employeeCount integer ds formula="(SELECT COUNT(*) FROM person WHERE person.company = id)"
How do I set default values?
<enumset name="Priority">
<enum value="low">Low</enum>
<enum value="normal">Normal</enum>
<enum value="high">High</enum>
</enumset>
Task @Tasks order="dueDate"
title d r
dueDate date
createdOn datetime fixed default="now"
owner User fixed default="User:find(userId)"
priority enum enumset="Priority" default="normal"
done boolean default="false"
How do I show each user only their own records?
userId is the id of the logged-in user, and User is the model's user entity.
Request @Requests order="id desc" defaultlisting="mine"
<subset name="mine" order="id desc">
<condition field="requester" value="User:find(userId)" />
</subset>
<listing name="mine">
<tab name="mine" label="My requests" subset="mine" />
</listing>
requester User fixed default="User:find(userId)"
subject d r
How do I organize a long form?
Employee @HR order="lastName"
#tab Personal
firstName d r / lastName d r
birthDate date
personalEmail email
#tab Job
department Department r
position r
startDate date r
How do I define a list of fixed values?
<enumset name="Priority">
<enum value="low">Low</enum>
<enum value="normal">Normal</enum>
<enum value="high">High</enum>
</enumset>
Task @Tasks order="title"
title d r
priority enum enumset="Priority" default="normal"
How do I model a many-to-many relationship?
For a plain association, use a collection of references:
Article @Content order="title"
title d r
tags Tag set
When the relationship has its own data (a grade, a date, a role), make it an entity and name it by its meaning:
Enrollment @Academic order="id desc"
student Student d r
course Course d r
enrolledOn date r default="now"
grade double
How do I prevent records from being created or removed by hand?
AuditEntry @System noadd="noadd" noremove="noremove" order="timestamp desc"
timestamp datetime d fixed
user User ds fixed
description fixed
Records are then created only by operations or by code.