Files
NativeScript/ui/core/bindable.ts
2014-06-12 17:44:23 +03:00

121 lines
3.1 KiB
TypeScript

import observable = require("ui/core/observable");
export interface BindingOptions {
sourceProperty: string;
targetProperty: string;
twoWay?: boolean;
}
export class Bindable extends observable.Observable {
private _bindings = {};
public bind(source: observable.Observable, options: BindingOptions) {
var binding: Binding = this._bindings[options.targetProperty];
if (binding) {
binding.unbind();
}
binding = new Binding(this, options);
this._bindings[options.targetProperty] = binding;
binding.bind(source);
}
public unbind(options: BindingOptions) {
var binding: Binding = this._bindings[options.targetProperty];
if (binding) {
binding.unbind();
delete this._bindings[options.targetProperty];
}
}
public updateTwoWayBinding(propertyName: string, value: any) {
var binding: Binding = this._bindings[propertyName];
if (binding) {
binding.updateTwoWay(value);
}
}
public setPropertyCore(data: observable.PropertyChangeData) {
super.setPropertyCore(data);
this.updateTwoWayBinding(data.propertyName, data.value);
}
public getBinding(propertyName: string) {
return this._bindings[propertyName];
}
private clearBinding(binding: Binding) {
binding.unbind();
}
}
class Binding {
options: BindingOptions;
updating = false;
source: observable.Observable;
target: Bindable;
callback: (data: observable.PropertyChangeData) => void;
constructor(target: Bindable, options: BindingOptions) {
this.target = target;
this.options = options;
}
public bind(obj: observable.Observable) {
this.source = obj;
this.updateTarget(this.source.getProperty(this.options.sourceProperty));
var that = this;
this.callback = function (data: observable.PropertyChangeData) {
that.onSourcePropertyChanged(data);
}
this.source.addObserver(observable.Observable.propertyChangeEvent, this.callback);
}
public unbind() {
if (!this.source) {
return;
}
this.source.removeObserver(observable.Observable.propertyChangeEvent, this.callback);
this.source = undefined;
this.target = undefined;
}
public updateTwoWay(value: any) {
if (this.options.twoWay) {
this.updateSource(value);
}
}
public onSourcePropertyChanged(data: observable.PropertyChangeData) {
if (data.propertyName !== this.options.sourceProperty) {
return;
}
this.updateTarget(data.value);
}
private updateTarget(value: any) {
if (this.updating) {
return;
}
this.updating = true;
this.target.setProperty(this.options.targetProperty, value);
this.updating = false;
}
private updateSource(value: any) {
if (this.updating) {
return;
}
this.updating = true;
this.source.setProperty(this.options.sourceProperty, value);
this.updating = false;
}
}