Terminal TAST

Property binders

TAST binding function requires that the view model follows the same structure of the TAST objects. When this is not possible, use property binders to compute specific elements in the TAST document.

Quick Example

The current example has two steps (see index.js):

  • bind

    Generates a new tast from an existing tast by adding view model values to it.

  • spliceTerminalTAST

    Loads the TAST into the terminal.

The bind tast implies that there are at least two TAST: the TAST before binding a view model, and the TAST after it.

In the previous example the TAST (tast.json) before binding is:

Copy
[
  "> ",
  { "type": "Bind", "property": "wave" },
  " ",
  {
    "type": "Inline",
    "inlineType": "highlighted",
    "children": [{ "type": "Bind", "property": "name" }]
  },
  "."
]

And it can be represented as a tree:

The bind method looks for all bindthings inside. In this example it needs to bind a property called wave and a property called name.

The example shows two ways of binding data: one by providing a view model, and another by providing generator functions called property binders.

The view model (vm.json) is the following:

Copy
{
  "name": "david"
}

It gives the value for name so bind can replace it.

But there is no value for wave. It is provided by the property binders (propertyBinders.js):

Copy
export default {
  '$.wave': () => (Math.random() < 0.5 ? 'Hello' : 'Hola'),
};

The $.wave is the JSONpath that describes which is the property that binds. The result of the function is the actual value used in the binding.

Apply both, view model and the property binders with the bind function:

Copy
const boundTAST = tastHelper.bind(tast, vm, propertyBinders;)

The resulting boundTAST is the following:

Copy
[
  "> Hello ",
  {
    "type": "Inline",
    "inlineType": "highlighted",
    "children": ["david"]
  },
  "."
]

And the equivalent graph:

Copy
const vm = {
  name: 'david',
};

const propertyBinders = {
  '$.wave': () => 'Hola',
};

const boundTAST = tastHelper.bind(tast, vm, propertyBinders);

Follow the path

Property binders instruct the bind function how to obtain a value. It uses pairs of JSON path and corresponding function generator.

Object properties

The JSON path resembles how we access to an element in javascript. Write in the property name which path you want, and then a function that generates the given value.

Overwrites the value

The propertyBinder precedes the ViewModel. If the ViewModel has the property, but there is a propertyBinder for it, it chooses the value from the property binder.

Enhances the value

The propertyBinder first argument is the ViewModel. Use the value of the current ViewModel to enhance it or transform it into a new value.

Crossing unexisting objects

You can define any deepness in the object structure. If parent objects does not exists in the ViewModel BindObject does not fails and allows to proceed as long as the final Bind requires a property that it is defined by a propertyBinder.

Collections

Arrays

You can create arrays and collections in the property binders. Just create a list with the elements that you need.

Objects inside arrays

Create objects inside arrays using star * JSONpaths. It injects the crossed indexes into the second argument of the propertyBinder as indexes.

Arrays inside arrays

You can define the property binders for any arbitrary deepness in arrays. The indexes injected property collects all crossed indexes. Deeper indexes are the latest elements in the array.

Objects keys

As well as arrays you can use the star * to traverse all object properties. In this case, the indexes injected property contains the key of the traversed object.

Accessing collections

Indexes are tracked and injected so you can retrieve them to query data. Collections are also tracked and injected so you can use them. Like indexes, collections contains all traversed collections with star * (arrays, or objects) so you can retrieve their data.