Verified Commit 8db6f21c authored by Mark van den Brink's avatar Mark van den Brink
Browse files

Finalize docs

parent 79f35adf
......@@ -4,12 +4,12 @@ title: Blocks
---
### Taking hardcore charge
Perhaps one of the best things about Tripetto is that you decide which form *building blocks* (e.g. question types) you want to use in the editor and collector. We offer a default set to choose from, but you can also develop your own. The building blocks’ behaviors are defined in so-called **blocks**.
Perhaps one of the best things about Tripetto is that you decide which form *building blocks* (e.g. question types) you want to use in the editor and collector. We offer a default set to choose from, but you can also develop your own building blocks.
**In one single package a block typically both:**
- Holds the programmable behavior of a particular building block (e.g. [dropdown](https://www.npmjs.com/package/tripetto-block-dropdown){:target="_blank"}, [checkbox](https://www.npmjs.com/package/tripetto-block-checkbox){:target="_blank"}, etc.);
- **And** facilitates the management of its properties through the editor.
- Holds the properties of a particular building block (e.g. [dropdown](https://www.npmjs.com/package/tripetto-block-dropdown){:target="_blank"}, [checkbox](https://www.npmjs.com/package/tripetto-block-checkbox){:target="_blank"}, etc.);
- **And** facilitates the management of those properties through the editor.
For building blocks we recommend using [TypeScript](https://www.typescriptlang.org/){:target="_blank"}. We supply typings to enable optimal [IntelliSense](https://code.visualstudio.com/docs/editor/intellisense){:target="_blank"} support.
{: .info }
......
......@@ -4,7 +4,7 @@ bookmark: concepts
title: Concepts
---
This is a good time to highlight again that we built a 2D drawing board because we think that's the best way to visualize and edit an advanced form; especially if it supports logic and conditional flow to smartly adapt to respondents' inputs. This generally shortens forms and enhances their responsiveness. So instead of being a [WYSIWYG](https://en.wikipedia.org/wiki/WYSIWYG){:target="_blank"} editor, it presents the structural layout of a form's flow and lets you easily move around building blocks on a self-organizing grid.
This is a good time to highlight again that we built a 2D drawing board because we think that's the best way to visualize and edit an advanced form or survey; especially if it supports logic and conditional flow to smartly adapt to respondents' inputs. This generally shortens forms and enhances their responsiveness. So instead of being a [WYSIWYG](https://en.wikipedia.org/wiki/WYSIWYG){:target="_blank"} editor, it presents the structural layout of a form's flow and lets you easily move around building blocks on a self-organizing grid.
This is where blocks also come in. These **node blocks** and **condition blocks** essentially define building block behaviors in a form and dictate what properties and **feature cards** to unlock in the editor for their configuration. A block instructs the editor. And when instructed correctly by properly formatted block **interfaces**, the editor will know everything it needs to know to handle the pertaining building block on the drawing board and the collector can collect respondent inputs in so-called **slots**.
......@@ -32,9 +32,9 @@ One or more *clusters* can form a *branch*. A branch can be conditional. You can
A *branch* can contain one or more *conditions*, which are used to direct flow into the branch. They are evaluated when a cluster ends. Only subsequent branches with matching condition(s) are taken by the collector. Just like nodes, the conditions are actually placeholders for condition behaviors. The condition behavior itself is defined in a *condition block*.
#### `Blocks`
So, blocks supply a certain behavior to node and condition building blocks that are used in the editor to build smart forms. As mentioned before blocks come in two flavours:
So, blocks supply a certain behavior to nodes and conditions that are used in the editor to build smart forms. As mentioned before blocks come in two flavours:
- *Node blocks*: Provide building blocks for nodes (for example [text input](https://www.npmjs.com/package/tripetto-block-text){:target="_blank"}, [dropdown](https://www.npmjs.com/package/tripetto-block-dropdown){:target="_blank"}, [checkbox](https://www.npmjs.com/package/tripetto-block-checkbox){:target="_blank"} etc.);
- *Condition blocks*: Provide building blocks for conditions.
- *Condition blocks*: Provide building blocks for conditions (for example evaluate a certain given answer).
#### `Slots`
All data collected through the [collector](../collector/) needs to be stored somewhere. In Tripetto we use `Slots` to do this. Slots are also defined by blocks. For example, if you build a text-input block, you're probably going to retrieve a text value from an input control in your collector implementation. In that case your block should create a slot to store this text value. There are different types of slots, such as a `StringSlot`, `BooleanSlot` or `NumberSlot`.
......@@ -61,7 +61,7 @@ code: |
{: title="webpack.config.js" }
---
Blocks for Tripetto are actually [packages](https://docs.npmjs.com/how-npm-works/packages){:target="_blank"}. A package is a directory that is described by a `package.json` and so is a block. The most important part of the package configuration is the `main`-field. This field contains the entry point of your block. The entry point is used when the Tripetto editor wants to load your block. If you want you can include multiple blocks in a single package. But we'll assume for now that you create a package for each block.
Blocks for Tripetto are actually [packages](https://docs.npmjs.com/how-npm-works/packages){:target="_blank"}. A package is a directory that is described by a `package.json` and so is a block. The most important part of the package configuration is the entry point of the block. Normally defined by the `main`-field. The entry point is used when the Tripetto editor wants to load your block. If you want you can include multiple blocks in a single package. But we'll assume for now that you create a package for each block.
The minimal package file for a block should look like this:
......
......@@ -115,12 +115,12 @@ export class Example extends NodeBlock {
##### **name**
{: .decorator }
{: .optional }
Specifies whether a property influences the name of the block as displayed in the editor. When you apply this decorator to a property the block name will be updated when the property value is changed. This requires you to override the `Name` property, because by default the name is always equal to the fixed block name specified by the `@node` decorator.
Specifies whether a property influences the name of the block as displayed in the editor. When you apply this decorator to a property the block name will be updated when the property value is changed. This also requires you to override the `Name` property, because by default the name is always equal to the fixed block name specified by the `@node` decorator.
##### **icon**
{: .decorator }
{: .optional }
Specifies whether a property influences the icon of the block as displayed in the editor. When you apply this decorator to a property the block icon will be updated when the property value is changed. This requires you to override the `Icon` property, because by default the icon is always equal to the fixed block icon.
Specifies whether a property influences the icon of the block as displayed in the editor. When you apply this decorator to a property the block icon will be updated when the property value is changed. This also requires you to override the `Icon` property, because by default the icon is always equal to the fixed block icon.
##### **Name**
{: .property }
......@@ -173,7 +173,7 @@ Invoked when the block is initialized. This is right after the block instance is
{: .method }
{: .event }
{: .optional }
Invoked when the block is assigned to a node. If there was an other block attached to the node it is supplied as parameter. You could use it to derive data from the previous block.
Invoked when the block is assigned to a node. If there was another block attached to the node it is supplied as parameter. You could use it to derive data from the previous block.
`previous`
: Reference to the previous attached block (or `undefined` if there was none).
......
......@@ -132,7 +132,7 @@ Invoked when the block is initialized. This is right after the block instance is
{: .method }
{: .event }
{: .optional }
Invoked when the block is assigned to a condition. If there was an other block attached to the condition it is supplied as parameter. You could use it to derive data from the previous block.
Invoked when the block is assigned to a condition. If there was another block attached to the condition it is supplied as parameter. You could use it to derive data from the previous block.
`previous`
: Reference to the previous attached block (or `undefined` if there was none).
......
......@@ -18,7 +18,7 @@ To avoid duplicate interface declarations or mismatches between the properties,
![Blocks diagram](../images/diagrams/blocks.svg)
#### Editor domain
The following example shows how to achieve this in the editor domain. First off we define the interface in a type declaration file, for example `interface.d.ts`. We use a type declaration file and consume the required symbols from the module `@tripetto/map`. This module is included in both the `{{ site.npm_packages.editor }}` and the `{{ site.npm_packages.collector }}` package.
The following example shows how to achieve this in the editor domain. First off we define the interface in a separate type declaration file, for example `interface.d.ts`. We consume the required symbols from the module `@tripetto/map`. This module is included in both the `{{ site.npm_packages.editor }}` and the `{{ site.npm_packages.collector }}` package. So it works in both domains.
```typescript
import { INodeBlock } from "@tripetto/map";
......
......@@ -32,8 +32,8 @@ This will show the feature in the feature list. When a feature is selected, the
### Building feature cards
Tripetto contains a collection of form controls that can be used to build form cards for the feature cards in the editor. The table below shows the available controls. These controls can be used in the `Controls` array of the form card.
| Form control | Description |
|-------------------------|----------------------------|
| Form control | Description |
|----------------------|----------------------------|
| `Forms.Button` | Button form control. |
| `Forms.Checkbox` | Checkbox form control. |
| `Forms.Date` | Date/time form control. |
......@@ -59,7 +59,7 @@ properties.Features.Feature(
Title: "Example",
Controls: [
new Forms.Text("single").Label("This is a text input"),
new Forms.Checkbox("This is a checkbox"),
new Forms.Checkbox("This is a checkbox")
]
}));
```
......@@ -68,7 +68,7 @@ properties.Features.Feature(
If you dive deeper into the controls, you will see each control has events you can bind to. One of these events is invoked when the data of the control changes. But there is an easier way to retrieve data from controls by using the stream option of supported controls. If a control has a `Stream` method it supports data streaming. The stream method takes 3 parameters:
- A reference to the object that holds the property the control is going to set;
- The name of the property;
- The default value that's applied as long if the control has no value.
- The default value that's applied as long as the control has no value.
Let's extend our example with the control stream.
......@@ -96,11 +96,11 @@ properties.Features.Feature(
Now the supplied properties `Text` and `Checked` will be automatically updated when the data of the control changes.
### Common features
The following common features are available.
Common features are out-of-the-box available sets of form controls to manage often used properties. The following common features are available.
| Feature | Explanation |
|----------------------------|-------------------------------------------------------------|
| `Features.Static` | Contains static feature titles. |
| `Features.Static` | Contains common feature titles. |
| `Features.Name` | Sets the name of a node. |
| `Features.Description` | Sets the description of a node. |
| `Features.Placeholder` | Sets the placeholder of a node. |
......
......@@ -61,7 +61,7 @@ When you prefix the collection member with the `@definition` decorator, the coll
{: .info }
### Showing the collection in the feature card
The final step is to show the collection editor in the feature card of your block. To do so, you should add a feature for the collection to your `OnProperties` implementation. Use the `Features.Collection` card (a collection editor). It supports adding, editing and deleting items.
The final step is to show the collection editor in the feature card of your block. To do so, you should add a feature for the collection to your `OnProperties` implementation. Use the common `Features.Collection` card (a collection editor). It supports adding, editing and deleting items.
```typescript
properties.Features.Card(
......
......@@ -6,7 +6,7 @@ title: Condition create templates
indent: true
---
When you implement a node block, it is possible to supply condition create templates to the editor. These templates can be used to allow the creation for your block in the editor of actual conditions in one click. The templates will be shown when the user wants to add a condition to a certain node. To make this work you can return an array with condition create templates from your node block. This is done using the `OnConditionTemplates` method.
When you implement a node block, it is possible to supply condition create templates to the editor. These templates can be used to allow the creation of actual conditions for your block in the editor with one click. The templates will be shown when the user wants to add a branch to a certain cluster. To make this work you can return an array with condition create templates from your node block. This is done using the `OnConditionTemplates` method.
```typescript
...
......
......@@ -39,7 +39,7 @@ A *branch* can contain one or more *conditions*, which are used to direct flow i
#### `Instances`
When a a valid [form definition](../editor/#definitions) is provided to the collector a so-called *instance* can be started. An instance represents a single input/user session. As long as the form is not completed, the related instance remains active. When an instance is started, the first cluster with nodes is automatically displayed. And when eventually there are no more clusters to display, the form is considered complete. The instance is then ended, an appropriate event emitted and the collected form input data provided.
**BTW**, instances can also be paused and resumed later on. In a typical UI-oriented application only one instance at a time can be active. More complex use cases are conceivable, but out of scope of this documentation.
**BTW**, instances can also be paused and resumed later on. In a typical UI-oriented application only one instance at a time can be active. More complex use cases are conceivable, but out of scope of this documentation for now.
{: .info }
#### `Slots`
......
......@@ -99,7 +99,7 @@ export class YourBlock extends NodeBlock<Rendering, Properties> {
public OnRender(
instance: Instance,
action: Await): Rendering {
// Invoked when the block should return it's rendering
// Invoked when the block should return or do it's rendering
}
public OnValidate(
......
......@@ -29,11 +29,11 @@ The easiest way to retrieve all collected data is through the `Values` property
}
}
```
As you can see the values are stored using the slot hash as a key. You can retrieve a collection of slots using the `Slots` property of an instance. Each slot value contains the name of the slot. If a slot alias is set, this alias is used as name. Otherwise the slot name or placeholder will be used. It is possible multiple values for a certain slot are stored. This will occur when your form definition contains branches that use the culling mode *each*. This will iterate a branch for each matching condition, instead of only for the first matching condition. In the survey world this feature is often referred as *piping*: The same set of questions are repeatedly asked for certain given answers or subjects. Tripetto forms supports piping in its core.
As you can see the values are stored using the slot hash as a key. You can retrieve a collection of slots using the `Slots` property of an instance. Each slot value contains the name of the slot. If a slot alias is set, this alias is used as name. Otherwise the slot name or placeholder will be used. It is possible multiple values for a certain slot are stored. This will occur when your form definition contains branches that use the culling mode *each*. This will iterate a branch for each matching condition, instead of only for the first matching condition. In the survey world this feature is often referred as *piping*: The same set of questions are repeatedly asked for certain given answers or subjects. Tripetto supports piping in its core.
If a slot value is established for normal branches the value of a slot is always stored under the `*` key. This is the global value of a slot since it is amassed in the global context.
When a slot value is established from a branch that is iterated multiple times for multiple conditions, the key is calculated using the condition hashes that are stored in the `Context` array of a value. This array contains the condition hash(es) of the active condition(s) for a certain iteration. These conditions effectively determine the context of stored the value.
When a slot value is established from a branch that is iterated multiple times for multiple conditions, the key is calculated using the condition hashes that are stored in the `Context` array of a value. This array contains the condition hash(es) of the active condition(s) for a certain iteration. These conditions effectively determine the context of the stored value.
Let's explain that using the following example. Imagine you have a form definition with a certain branch which is taken for two conditions (the complete branch is iterated for each condition). This will result in the following data collection:
......@@ -65,7 +65,7 @@ Let's explain that using the following example. Imagine you have a form definiti
The context array of a slot value can contain multiple condition hashes if a combination of conditions is active. This combination of conditions forms the context in which the value is established.
The keys for the contextual slot values are composed using the condition hashes of the context. If the context is global the key of that value is always `*`. If the context array contains a single condition, the value key is the hash of that condition. If the context array contains 2 or more conditions, the hashes of these conditions are used to calculate a new hash. The condition hashes are concatenated in chronological order and then a `SHA2_256` hash is generated for this concatenated string. This hash is used as key.
The keys for the contextual slot values are composed using the condition hashes of the context. If the context is global the key of that value is always `*`. If the context array contains a single condition, the value key is the hash of that single condition. If the context array contains 2 or more conditions, the hashes of these conditions are used to calculate a new hash. The condition hashes are concatenated in chronological order and then a `SHA2_256` hash is generated for this concatenated string. This hash is used as key.
{: .info }
### Hook to an instance
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment