jwidget/DestroyableBindable

Consumption

import DestroyableBindable from "jwidget/DestroyableBindable";

Default export#

Hierarchy#

Description#

V
Value type.

Extension of Bindable interface with destroy method. If some method returns DestroyableBindable, probably it establishes some kind of binding and wants you to take control over its life time. Usually that means that you must aggregate it via own method.

In the next example, bindVal function returns DestroyableBindable<string>, so we are supposed to aggregate it. Life time of ValueLogger can be shorter than el element life time, so ValueLogger must aggregate the binding to cancel it on destruction.

Example 1. Value logger#
class ValueLogger extends Class {
    constructor(el: JQuery) {
        super();
        const value = this.own(bindVal(el));
        value.map(value => console.log(value));
    }
}

In some cases, binding destruction is not obligatory. In the next example, the component binds a property to its own element, so the garbage collector will take everything away on component destruction anyway. So, it doesn't make much sense to aggregate the binding explicitly.

Example 2. Typical binding to own DOM element#
@template('<div><input type="text" jwid="input"></div>')
class App extends Component {
    renderInput(el: JQuery) {
        const value = bindVal(el);
        value.map(value => console.log(value));
    }
}

Fields#

onChange (inherited from Bindable)#

readonly onChange: Listenable<Bindable.ChangeMessage<V>>

Property value has just been changed. Dispatched in result of set method call if the value has been changed.

silent (inherited from Bindable)#

readonly silent: boolean

Checks if this property never dispatches messages. This knowledge may help you do certain code optimizations.

Methods#

destroy (inherited from Destroyable)#

(): void

Class destructor. You must override it in a subclass and call this method explicitly from outside, because JavaScript doesn't support automatic class destructor calling.

const object = new MyClass();

// ...

// When the object is not needed anymore, destroy it.
object.destroy();

Alternatively (and optimally), you should use own method to aggregate this object in another one.

get (inherited from Bindable)#

(): V

returns
Current property value.

Think twice before calling this method - probably it makes sense to use some kind of binding instead?

map (inherited from Bindable)#

<U>(create: (value: V) => U, config?: Mapper.Config<U>): DestroyableBindable<U>

create
Mapping function.
config
Configuration options.
returns
Mapped property.

Creates a new property bound to this property, keeping it equal to the result of a function call for value of this property. To stop the binding, you must destroy the resulting property. To map multiple properties at once, use Mapper.

Example 1. Double number
const num = new Property<number>(3);
const double = num.map(value => 2 * value);
expect(double.get()).equal(6);
num.set(5);
expect(double.get()).equal(10);

Pass destroy option to destroy the previously mapped values.

Example 2. Typical bindable model mapping to UI component
@template('<div><div jwid="report"></div></div>')
class App extends Component {
    constructor(private report: Bindable<Report>) {}

    protected renderReport() {
        return this.own(report.map(report => new ReportView(report), {destroy}));
    }
}

Pass viaNull option to reverse mapper updating flow. Default flow is:

  1. Create a new value.
  2. Reassign target property.
  3. Destroy the old value.

Setting this option to true changes the flow the next way:

  1. Set target value to null.
  2. Destroy the old value.
  3. Create a new value.
  4. Assign target property.