Imagine that we are collecting data about school pupils and their pets. We might design one Form to collect data about the pupil, and then a separate Form to be used for each pet that they own. In this design, however, we would need some way to express that each submission for the “pet” Form belongs to a particular submission for the “pupil” form. Apart from columns representing the data we are collecting for each pet (such as name, age etc), a database table holding entries for pets would also need a column holding a value for a foreign key that maps from each entry in the “pets” table to a particular entry in the “pupils” table.
To express this kind of relationship within Sapelli, the BelongsTo element is included within a Form description, with attributes used in order to declare which Form this one “belongs to” as well as how the “owning” Form should be presented to the user.
Note that BelongsTo can also be used to express one-to-one relationships between Form instances by setting the remember attribute to “false”.
It is possible to jump to a BelongsTo simply by setting the jump attribute of the source Field to the ID of the destination BelongsTo element. However to express the desire to edit a foreign Form after jumping to a BelongTo element, it is necessary to include an argument as a child element within the source Field:
<Argument param="edit" value="true"/>
Constraint elements are not Fields and can only be used as child elements of a relationship-denoting element, such as BelongsTo. They are used to impose constraints on the set of Form instances that can be included on the “foreign” side of that relationship, in a fashion similar to the constraints used when constructing a query on a relational database.
A Constraint is constructed by specifying the column that will be considered for constraint, and then the property with which to constrain values in this column. Continuing the example described above, when declaring that an instance of the “pet” Form belongs to an instance of the “pupil” Form we might want to only consider pupils who have confirmed that they do indeed own a pet. This would be achieved by adding a Constraint to our BelongsTo over some “hasPet” column such that the value in this column must equal “true”.
Each Constraint can only act on a single column, however if multiple Constraints are imposed on a single relationship then they will be combined with the “AND” operator.
Here is an example code:
<Form id="petForm" next="loopform" startField="petBelongsToPupil">
<BelongsTo form="petBelongsToPupil" remember="true" skipOnBack="true">
<Constraint column="closed" equal="false" />
<Button id="changePupil" column="none" caption="Press the button to return to editing data about the owner of this pet" jump="petBelongsToPupil">
<Argument param="edit" value="true"/>
... (Fields that collect information about the pet go here)
<Button id="Closed" column="boolean" optional="true" caption="Add another pupil" showOnCreate="false" jump="_SAVE+LOOPFORM"/>
... (Fields that collect information about the pupil go here)
Note the following things about this code:
- The pet Form (with ID “petForm”) specifies that it start with the BelongsTo field (with ID “petBelongsToPupil”). This leads the user to the “pupilForm” field before they may begin to enter information about the pet, so that every pet has an owner.
- The pet Form will loop on completion so the user will never progress to the pupil Form without going through the BelongsTo field.
- The BelongsTo field declares that the pet Form belongs to the pupil Form. Additionally, the instance of the pupil Form is remembered so that a pupil can have multiple pets.
- The Constraint added to the BelongsTo ensures that only pupils which are not “closed” (i.e. which have not been marked as “finished”) can be edited.
- To determine when a pupil Form instance is “closed”, a Button field is added to the pupil Form that allows the user to start editing the data for a new pupil. This saves their current entry and clears the Form so they can start again. In doing so they are closing the current pupil Form instance.
- One of the Fields included in the pet Form is a button (with ID “changePupil”) that allows the user to return to editing the current instance of the pupil Form (that represents the owner of this pet). This is achieved by specifying that pressing the button jumps the user to the BelongsTo field. An Argument is added to declare that the user may make changes to the pupil Form instance once they have jumped to it.
Click here to see the full list of attributes that you can include within the BelongsTo and Constraint tags.