14

out of curiosity and to increase my knowledge, i wanted to implement some kind of two way data binding between dom elements and javascript variables.

I was lucky enough to find an excellent answer to half of my problem here @ stackoverflow which led me to this gist https://gist.github.com/384583, but i still can't get the thing done at 100%.

Here's an example of my code: http://jsfiddle.net/bpH6Z/

If you try to run the fiddle and click on "view Value" you will get undefined, while i want to get the actual value of the object's attribute.

I am probably doing something wrong due to my lack of experience with javascript, but do you have any idea why i can't properly read the attribute 'secret' after the _bind() and _watch() calls?

DISCLAIMER: as i said, i'm doing this because i want better knowledge of javascript, and i am not going to write my framework. So any "USE FRAMEWORK X" is completely useless, as i could get the job done with angularjs.

2

3 Answers 3

5

Please try http://jsfiddle.net/bpH6Z/4/

I've updated your redefined getter/setter in Object.prototype.__watch, also currently your handler needs to return the new value.

Update: Now your handler isn't required to return the newly set value.

Current code:

//Got this great piece of code from https://gist.github.com/384583
Object.defineProperty(Object.prototype, "__watch", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function(prop, handler) {
        var val = this[prop],
            getter = function() {
                return val;
            },
            setter = function(newval) {
                val = newval;
                handler.call(this, prop, newval);
                return newval;
            };

        if (delete this[prop]) { // can't watch constants
            Object.defineProperty(this, prop, {
                get: getter,
                set: setter,
                enumerable: true,
                configurable: true
            });
        }
    }
});

var Controller = function () {
    //The property is changed whenever the dom element changes value
    //TODO add a callback ?
    this._bind = function (DOMelement, propertyName) {
        //The next line is commented because priority is given to the model
        //this[propertyName] = $(DOMelement).val();
        var _ctrl = this;
        $(DOMelement).on("change input propertyChange", function(e) {
            e.preventDefault();
            _ctrl[propertyName] = DOMelement.val();
        });

    };

    //The dom element changes values when the propertyName is setted
    this._watch = function(DOMelement, propertyName) {
        //__watch triggers when the property changes
        this.__watch(propertyName, function(property, value) {
            $(DOMelement).val(value);
        });
    };
};

var ctrl = new Controller();
ctrl.secret = 'null';
ctrl._bind($('#text1'), 'secret'); // I want the model to reflect changes in #text1
ctrl._watch($('#text2'), 'secret'); // I want the dom element #text2 to reflect changes in the model
$('#button1').click(function() {
    $('#output').html('Secret is : ' + ctrl.secret); //This gives problems
});

Current HTML:

<html>
<head></head>
<body>
    value: <input type="text" id="text1" /><br />
    copy: <input type="text" id="text2" /><br />
    <input type="button" id="button1" value="View value"><br />
    <span id="output"></span>
</body>
</html>
Sign up to request clarification or add additional context in comments.

2 Comments

Would this work with IE8 as defineProperty only works on DOM objects?
@Integralist most likely not, but one should give it a try - have to reboot to xp
3

The handler you pass to your __watch function is missing a return statement.

this._watch = function(DOMelement, propertyName) {
    //__watch triggers when the property changes
    this.__watch(propertyName, function(property, value) {
        $(DOMelement).val(value);
        return value;
    })

}

Because newval is set to what's returned from the handler, it'll be undefined without that.

1 Comment

+1. Spot on, beat me to it... I just noticed this finally too
0

I have enhanced it for multi-watchers.

http://jsfiddle.net/liyuankui/54vE4/

//The dom element changes values when the propertyName is setted
this._watch = function(DOMelement, propertyName) {
    //__watch triggers when the property changes
    if(watchList.indexOf(DOMelement)<0){
        watchList.push(DOMelement);
    }
    this.__watch(propertyName, function(property, value) {
        for(var i=0;i<watchList.length;i++){
            var watch=watchList[i];
            $(watch).val(value);
            $(watch).html(value);
        }
    });
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.