Zorak
Zorak

Reputation: 709

JS multiple data binding overwriting

I need to implemennt data binding or any other kind of variable observer, whenever the variable changes, trigger some defined action. We are also talking about pure JS, I do not want to use any kind of framework or library due to the performance issues.

I have found a pretty simple and nice data binding code, but its behavior is quite wierd. It works only if you try to bind only 1 variable. Whenever you try to bind multiple variables, it will bind all actions to the last element, even if the bindings was called separately to different variables.

function Binding(b) {
	_this = this
	this.element = b.element
	this.value = b.object[b.property]
	this.attribute = b.attribute
	this.valueGetter = function(){
		return _this.value;
	}
	this.valueSetter = function(val){
		_this.value = val
		_this.element[_this.attribute] = val
	}

	Object.defineProperty(b.object, b.property, {
		get: this.valueGetter,
		set: this.valueSetter
	});	
	b.object[b.property] = this.value;
	
	this.element[this.attribute] = this.value
}


var obj = {a:123, b:456, c:789};
var myElement = document.getElementById("myText");
var a = new Binding({
	object: obj,
	property: "a",
	element: document.getElementById("myText"),
	attribute: "value",
});

var b = new Binding({
	object: obj,
	property: "b",
	element: document.getElementById("myText2"),
	attribute: "value",
});

var c = new Binding({
	object: obj,
	property: "c",
	element: document.getElementById("myText3"),
	attribute: "value",
});

setInterval(function(){
for(var key in obj)
{obj[key]++;} }, 1000);
<input type=text id="myText"/>
<input type=text id="myText2"/>
<input type=text id="myText3"/>

Any idea please, how to alter the code in such a way, that I can bind the variables separately? I have tried to play with .bind() like if the "this" is overwriting something, I tried to play with rewriting function Bind to class, but so far with no results ...

Any help appreciated, thanks!

Upvotes: 2

Views: 325

Answers (1)

Andrew Koster
Andrew Koster

Reputation: 1845

Just use arrow functions to avoid redefining "this" and to avoid having to hack around it with a global variable:

function Binding(b) {
    this.element = b.element
    this.value = b.object[b.property]
    this.attribute = b.attribute
    this.valueGetter = () => {
        return this.value;
    }
    this.valueSetter = (val) => {
        this.value = val
        this.element[_this.attribute] = val
    }

    Object.defineProperty(b.object, b.property, {
        get: this.valueGetter,
        set: this.valueSetter
    }); 
    b.object[b.property] = this.value;

    this.element[this.attribute] = this.value
}

You could also use const, let, or var when defining _this, as a patch on top of your _this hack. But arrow functions avoid the _this hack in the first place. They're designed to avoid the scoping issues that led to the _this hack.

Upvotes: 1

Related Questions