Skip to content

Version 3.7.0

Compare
Choose a tag to compare
@tbuschto tbuschto released this 01 Dec 17:16
· 75 commits to master since this release

Security

Authentication

SubtleCrypto

Module System

New method Module.addPath

Module.addPath allows to define path aliases to make imports more consistent. It supports the TypeScript compiler "paths" option.

New method Module.define

Module.define can create new modules at runtime, for example to dynamically override file modules.

Widgets

CollectionView reveal with offset

beforeTextChange

Event System

Observables

Tabris now provides an implementation of the proposed Observable API. It has been integrated in to the event system so you can get observables for specific events (e.g. button.onSelect.subscribe(...)), property values (via change events, e.g checkBox.onCheckedChanged.values.subscribe(...)), or any object emitting Tabris.js change events (Observable.mutations(widget).subscribe(...)). It is also RxJS compatible via their from method:

rxjs.from(button.onSelect)
  .pipe(debounceTime(100))
  .subscribe(ev => ...);

Declarative UI

"Set" renamed to "Setter" to avoid confusion

Set was introduced in 3.6 as a helper function for use with composite.apply. When imported it shadowed the Set class built in to JavaScript. While this was considered acceptable at the time, it caused more issue than inticipated, so it was renamed to Setter. For backwards compatibility the function is also still exported as Set as an alias, but only documented as Setter.

"apply" is now declarative, supports new syntax

The "apply" method of Composite can now be invoked in a declarative way using either the attribute apply or the new JSX element <Apply>. It can also, in addition to the established syntax, be given an array of Setter elements (or a single one) for shorter syntax with better tooling support. This is a very convinient way to remove repetition in your UI code akin to CSS in HTML.

This example uses the apply attribute to create 3 TextView widgets that share a set of properties:

contentView.append(
  Composite({
    padding: 8,
    apply: Setter(TextView, {
      top: 'prev() 10',
      background: '#66E',
      textColor: 'white',
      font: '24px'
    }),
    children: [
      TextView({text: 'Hello'}),
      TextView({text: 'Blue'}),
      TextView({text: 'World'})
    ]
  })
);

The apply method/attribute/element can now also react to any property change of the widget it is called on. This can be used to write concise custom or functional components that update their content due to a change in any of their properties.

JSX element "Setter"

The Setter function can also be used as a JSX element to set any attribute its parent. This includes listeners and callbacks, so for example the CollectionView JSX element could now contain it's own cell factory:

  <CollectionView stretch itemCount={people.length} cellHeight={256} updateCell={updateCell}>
    <Setter target={CollectionView} attribute='createCell'>{() =>
      <Composite onTap={handleTap}>
        <ImageView top={16} centerX={0} width={200} height={200}/>
        <TextView left={30} top='prev() 16' right={30} alignment='centerX'/>
      </Composite>}
    </Setter>
  </CollectionView>

In general it's useful in any scenario where an attribute value would otherwise be too long for inlining.

Decorators

One-Way data binding via "@Bindall"

The "@Bindall" decorator can now be used to create one-way data bindings (in any direction) between a model and a child of a custom component, or the custom component itself. This is an alternative to the JSX based on-way data binding that may be more consistent when using the MVVM pattern.

Property based Dependency Injection

The "@Inject" decorator can now also be applied to properties, not just constructor parameters. This can be helpful to resolve circular dependency issues and result in an overall less cluttered constructor.