locked
More questios about the WinJS.Binding object

    Question

  • Hello guys.

    After a little more time playing with the binding object, I've got a couple of questions:

    1. what's the purpose of WinJS.Binding.oneTime? The docs say: "Sets the destination property to the value of the source property.". Why should I use this instead of simply setting the property of the control?

    2. what about WinJS.Binding.defaultBind? I'm under the impression that I should use it to create a binding object from code (ie, to produce the same result as we get from the data-win-bind in html). If this is the case, why do we have only a quick start showing how to use the bind method (which will only make me get a function call in response to a specific property change? One more: the docs (http://msdn.microsoft.com/en-us/library/windows/apps/br211691.aspxsay that defaulBind returns an object with a cancel method which is used to coallesce bindings. It this correct? does this mean that after calling this method, all changes in a property will end up generating notifications (vs several changes generating only one change notification)?

    3. Looking at the docs, I can also see the setProperty and updateProperty methods. It seems like setProperty will simply call updateProperty. Why do we have the 2 methods?

    4. btw, I'm assuming that all these property related methods will probably be used internally by observable objects, right?

    5. last one: if I declare a binding declaratively in the markup, is there any way to cancel it later? For instance, I'm under the impression that bindings created from bind can be "cancelled" by calling <strike>unbind</strike> the cancel method over the returned object (unbind no longer exists in the consumer preview). is there any way to do that to a binding defined in HTML?

    thanks


    Luis Abreu


    • Edited by Luis Miguel AbreuMVP Friday, March 23, 2012 3:04 PM Updated text to reflect the current version of the APIs
    Thursday, March 22, 2012 3:35 PM

Answers

  • Hello guys.

    After a little more time playing with the binding object, I've got a couple of questions:

    1. what's the purpose of WinJS.Binding.oneTime? The docs say: "Sets the destination property to the value of the source property.". Why should I use this instead of simply setting the property of the control?

    2. what about WinJS.Binding.defaultBind? I'm under the impression that I should use it to create a binding object from code (ie, to produce the same result as we get from the data-win-bind in html). If this is the case, why do we have only a quick start showing how to use the bind method (which will only make me get a function call in response to a specific property change? One more: the docs (http://msdn.microsoft.com/en-us/library/windows/apps/br211691.aspxsay that defaulBind returns an object with a cancel method which is used to coallesce bindings. It this correct? does this mean that after calling this method, all changes in a property will end up generating notifications (vs several changes generating only one change notification)?

    3. Looking at the docs, I can also see the setProperty and updateProperty methods. It seems like setProperty will simply call updateProperty. Why do we have the 2 methods?

    4. btw, I'm assuming that all these property related methods will probably be used internally by observable objects, right?

    5. last one: if I declare a binding declaratively in the markup, is there any way to cancel it later? For instance, I'm under the impression that bindings created from bind can be "cancelled" by calling unbind. is there any way to do that to a binding defined in HTML?

    thanks


    Luis Abreu

    1. DefaultBind attempts to make the object observable (it adds the observableMixin to your objects), and if there is an observable change to your object it will rebind to the target element (and therefore update the UI). The oneTime binding action eschews the observation code, and any updates to the object after binding will not be automatically mirrored in the UI.

    If you know you don't want your data to rebind automatically then you can use oneTime for a small performance enhancement (and a cumulative gain if you're binding a lot of static data).

    My Advice: if your data is static (or you rebind yourself) then use oneTime.

    2.  I don't know the answer to this one. You know: all of this WinJS.Binding code is mostly there to support WinJS.Binding.Template control and the declarative HTML markup for binding. If you're trying to reuse this code programmatically or piece-meal, you're probably doing yourself a disservice. You might be better off using a much less complex observation / eventing pattern (one that's not burdened with all the overhead and code to support the declarative markup scheme).

    3. See 2.

    4. Yes. See 2.

    5. Sorry, I don't know the answer to that one either.

    Thursday, March 22, 2012 10:03 PM
  • The performance gain would be use of oneTime over defualtBind. And that's only if you are using the declaritive binding markup. e.g.:

    This is a little faster for:

    <div data-win-bind="textContent: data.content WinJS.Binding.oneTime"></div>

    Than this:

    <div data-win-bind="textContent: data.content"></div>

    But this second one will update the UI if data.content changes.

    If you are writing javascript then you have no reason to use those binding functions. They're just complicated setters. For "one time" setting you would just do this instead:

    var a = { nome: { outro: "Luis" }, morada: "Funchal"};
    var b = { nome2: "", morada2:"" };
     
    b.nome2 = a.nome.outro;

    Furthermore, if you wanted to "b" to be updated when "a" changed, you would need to build some facility for making "a" observable. Here's an example:

    var simpleObservableMix = {
        _data: undefined,
        _observerStore: undefined,
        updateObservers: function updateObservers(data) {
            // notify the observers
            if (this._observerStore && this._observerStore.length) {
                var that = this; // forEach has a "this" scope change.
                this._observerStore.forEach(function (observer) {
                    observer(that._data);
                });
            }
        },
        data: {
            get: function dataGetter() {
                return this._data;
            },
            set: function dataSetter(value) {
                if (value) {
                    this._data = value;
                    this.updateObservers();
                }
            }
        },
        addObserver: function addObserver(observer) {
            if (!this._observerStore) {
                this._observerStore = [];
            }
    
            if (observer && typeof observer == 'function') {
                this._observerStore.push(observer);
                observer(this._data); // call it once the first time to make sure it's in sync.
            }
        }
    };
    
    var ObservableObject = WinJS.Class.define(function _constructor(data) {
        this.data = data;
    }, simpleObservableMix);
    
    var a = new ObservableObject({ nome: { outro: "Luis" }, morada: "Funchal" });
    var b = { nome2: "", morada2: "" };
    
    a.addObserver(function setToB(data) {
        b.nome2 = data.nome.outro;
    });
    
    a.data = { nome: { outro: "foo" }, morada: "Funchal" };
    
    b.nome2 === "foo";
    
    a.data = { nome: { outro: "bar" }, morada: "Funchal" };
    
    b.nome2 === "bar";
    

    My example observable class is very basic, if you look around the web there are better and more full-featured samples. Just be aware that the stuff in WinJS.Binding was built to be used for WinJS.Binding.Template and the other WinJS controls, and if you want to reuse that code in JavaScript then you're going to have to do a lot of work to read and understand how that code works.

    Long story short: the binding actions aren't intended to be used for programmatically setting the properties of one object to the properties of another. They're intended to be used to set the properties of an object to the properties of an HTML element in a declarative fashion.

    Friday, March 23, 2012 5:29 PM

All replies

  • Hello guys.

    After a little more time playing with the binding object, I've got a couple of questions:

    1. what's the purpose of WinJS.Binding.oneTime? The docs say: "Sets the destination property to the value of the source property.". Why should I use this instead of simply setting the property of the control?

    2. what about WinJS.Binding.defaultBind? I'm under the impression that I should use it to create a binding object from code (ie, to produce the same result as we get from the data-win-bind in html). If this is the case, why do we have only a quick start showing how to use the bind method (which will only make me get a function call in response to a specific property change? One more: the docs (http://msdn.microsoft.com/en-us/library/windows/apps/br211691.aspxsay that defaulBind returns an object with a cancel method which is used to coallesce bindings. It this correct? does this mean that after calling this method, all changes in a property will end up generating notifications (vs several changes generating only one change notification)?

    3. Looking at the docs, I can also see the setProperty and updateProperty methods. It seems like setProperty will simply call updateProperty. Why do we have the 2 methods?

    4. btw, I'm assuming that all these property related methods will probably be used internally by observable objects, right?

    5. last one: if I declare a binding declaratively in the markup, is there any way to cancel it later? For instance, I'm under the impression that bindings created from bind can be "cancelled" by calling unbind. is there any way to do that to a binding defined in HTML?

    thanks


    Luis Abreu

    1. DefaultBind attempts to make the object observable (it adds the observableMixin to your objects), and if there is an observable change to your object it will rebind to the target element (and therefore update the UI). The oneTime binding action eschews the observation code, and any updates to the object after binding will not be automatically mirrored in the UI.

    If you know you don't want your data to rebind automatically then you can use oneTime for a small performance enhancement (and a cumulative gain if you're binding a lot of static data).

    My Advice: if your data is static (or you rebind yourself) then use oneTime.

    2.  I don't know the answer to this one. You know: all of this WinJS.Binding code is mostly there to support WinJS.Binding.Template control and the declarative HTML markup for binding. If you're trying to reuse this code programmatically or piece-meal, you're probably doing yourself a disservice. You might be better off using a much less complex observation / eventing pattern (one that's not burdened with all the overhead and code to support the declarative markup scheme).

    3. See 2.

    4. Yes. See 2.

    5. Sorry, I don't know the answer to that one either.

    Thursday, March 22, 2012 10:03 PM
  • Hello Bryan.

    thanks for the reply!

    However, I'm still not sure about the oneTime method. Since I haven't gone into all the source code, I'll simply assume it's used internally. In fact, looking at the code seems to confirm that and I think it doesn't bring any additional value to the developer. For instance, it only allows me to "bind" (notice I'm using "" :)) one property at a time. even though it receives arrays, those arrays describe the path until the property. here's an example of what I mean:

    var a = { nome: { outro: "Luis" }, morada: "Funchal"};
    var b = { nome2: "", morada2:"" };
    WinJS.Binding.oneTime(a, ["nome", "outro"], b, ["nome2"]);

    Now, the previous code will only set b.nome2 to a.nome.outro. Now, I can't see any performance gains when using the oneTime vs setting the property directly...Why in the world would I want to use this? So, as I said, I'll assume that this is used internally and that the docs will reflect that when they get updated...

    Btw, if anyone knows the answer to the other questions, please do give me your feedback :)


    Luis Abreu

    Friday, March 23, 2012 9:45 AM
  • The performance gain would be use of oneTime over defualtBind. And that's only if you are using the declaritive binding markup. e.g.:

    This is a little faster for:

    <div data-win-bind="textContent: data.content WinJS.Binding.oneTime"></div>

    Than this:

    <div data-win-bind="textContent: data.content"></div>

    But this second one will update the UI if data.content changes.

    If you are writing javascript then you have no reason to use those binding functions. They're just complicated setters. For "one time" setting you would just do this instead:

    var a = { nome: { outro: "Luis" }, morada: "Funchal"};
    var b = { nome2: "", morada2:"" };
     
    b.nome2 = a.nome.outro;

    Furthermore, if you wanted to "b" to be updated when "a" changed, you would need to build some facility for making "a" observable. Here's an example:

    var simpleObservableMix = {
        _data: undefined,
        _observerStore: undefined,
        updateObservers: function updateObservers(data) {
            // notify the observers
            if (this._observerStore && this._observerStore.length) {
                var that = this; // forEach has a "this" scope change.
                this._observerStore.forEach(function (observer) {
                    observer(that._data);
                });
            }
        },
        data: {
            get: function dataGetter() {
                return this._data;
            },
            set: function dataSetter(value) {
                if (value) {
                    this._data = value;
                    this.updateObservers();
                }
            }
        },
        addObserver: function addObserver(observer) {
            if (!this._observerStore) {
                this._observerStore = [];
            }
    
            if (observer && typeof observer == 'function') {
                this._observerStore.push(observer);
                observer(this._data); // call it once the first time to make sure it's in sync.
            }
        }
    };
    
    var ObservableObject = WinJS.Class.define(function _constructor(data) {
        this.data = data;
    }, simpleObservableMix);
    
    var a = new ObservableObject({ nome: { outro: "Luis" }, morada: "Funchal" });
    var b = { nome2: "", morada2: "" };
    
    a.addObserver(function setToB(data) {
        b.nome2 = data.nome.outro;
    });
    
    a.data = { nome: { outro: "foo" }, morada: "Funchal" };
    
    b.nome2 === "foo";
    
    a.data = { nome: { outro: "bar" }, morada: "Funchal" };
    
    b.nome2 === "bar";
    

    My example observable class is very basic, if you look around the web there are better and more full-featured samples. Just be aware that the stuff in WinJS.Binding was built to be used for WinJS.Binding.Template and the other WinJS controls, and if you want to reuse that code in JavaScript then you're going to have to do a lot of work to read and understand how that code works.

    Long story short: the binding actions aren't intended to be used for programmatically setting the properties of one object to the properties of another. They're intended to be used to set the properties of an object to the properties of an HTML element in a declarative fashion.

    Friday, March 23, 2012 5:29 PM
  • Ah, you're comparing it with defaultBind...now I understand you're comparison and it makes total sense...

    thanks.


    Luis Abreu

    Friday, March 23, 2012 7:29 PM