How to bind a complex object (Windows Store apps using JavaScript and HTML)

3 out of 14 rated this helpful - Rate this topic

In many cases you want your app to bind to complex objects, in particular objects that manage processes that are not controlled by the app's UI. This topic shows how to write an app that displays data from an object that contains a name and a color, which is basically the same as the Quickstart: binding data and styles. In this case the object manages the change process itself, instead of responding to a button that triggers the change.

Prerequisites

Instructions

Step 1: Setting up a project to use binding

  1. Create a blank Windows Store app built for Windows using JavaScript and name it ObjectBinding.

  2. Add a DIV element for the binding and give it an ID of "objectBinding", an inner text of Welcome, and a SPAN element that has an ID of "bindableSpan", as shown here.

    
    <body>
        <div id="objectBinding">
          Welcome
          <span id="bindableSpan"></span>
        </div>
    </body>
    
    

Step 2: Setting up a complex object

  1. Define a Person object that has name and color fields, an array of names, an array of color names, and a private method to provide a random index for the array. For the definition of this object, you can use the WinJS.Class.define method.

    
    <script type="text/javascript">
        var Person = WinJS.Class.define(
            function() {
                this.name = "Harry";
                this.color = "blue";
                this.timeout = null;
            }, {
    
            _nameArray:
                new Array("Sally", "Jack", "Hal", "Heather", "Fred", "Paula", "Rick", "Megan", "Ann", "Sam"),
            _colorArray:
                new Array("lime", "lavender", "yellow", "orange", "pink", "greenyellow", "white", "lightblue", "lightgreen", "lightyellow"),
    
            _newName: function () {
                this.name = this._nameArray[this._randomizeValue()];
                this.color = this._colorArray[this._randomizeValue()];
            },
            _randomizeValue: function () {
                var value = Math.floor((Math.random() * 1000) % 8);
                if (value < 0)
                    value = 0;
                else if (value > 9)
                    value = 9;
                return value;
            }
        });
    </script>
    
    
  2. Now add to the Person definition two public methods that start and stop a process that changes the name and color fields every 500 milliseconds.

    
    start: function () {
        var that = this;
        if (this.timeout === null) {
            this.timeout = setInterval(function () { that._newName(); }, 500);
        }
    }, 
    
     stop: function () {
        if (this.timeout !== null) {
        clearInterval(this.timeout);
            this.timeout = null;
        }
    }
    
    

Step 3: Binding the object to the HTML

  1. Right now the Person object is not observable; that is, it does not provide notifications when it changes. We can make it observable by mixing the Person object with the correct binding functionality. The WinJS.Class.mix function adds to the Person object the functionality of the WinJS.Binding.mixin object, which includes a bind method, and the functionality of the WinJS.Binding.expandProperties function, which prepares the fields of the object for binding. Call WinJS.Class.mix after the Person object definition. (You need to define the Person class before you can mix anything with it.)

    
    WinJS.Class.mix(Person,
        WinJS.Binding.mixin,
        WinJS.Binding.expandProperties({name: "", color: ""})
    ); 
    
    
  2. You also need to call _initObservable inside the Person constructor to set up the _backingData property. Change the Person constructor as follows:

    
    
    ...
    function () {
        this._initObservable();
    
        this.name = "Harry";
        this.color = "blue";
        this.timeout = null;
        }
    ...
    
    
    
  3. After you have instantiated a Person object, you can bind it to the two properties. The bind method takes two parameters: the name of the property or field that is to be bound, and a function that specifies how it is to be bound. This function has two parameters: the new value and the old value. Because bind is an instance method, for now we'll just instantiate a Person and call bind on its name and color fields. Add the following code immediately after the call to WinJS.Class.mix.

    
    var myPerson = new Person();
    
    myPerson.bind("name", onNameChange);
    
    myPerson.bind("color", onColorChange);
    
    function onNameChange (newValue) {
        var span = document.getElementById("bindableSpan");
        span.innerText = newValue;
    }
    
    function onColorChange (newValue) {
        var span = document.getElementById("bindableSpan");
        span.style.color = newValue;
    }
    
    

    Warning  Do not attempt to bind data to the ID of an HTML element.

  4. To enable the change events to occur, you must change the _newname function so that it uses the setProperty method.

    
    _newName: function () {
        this.setProperty("name", this._nameArray[this._randomizeValue()]);
        this.setProperty("color", this._colorArray[this._randomizeValue()]);
        }
    
    
  5. You can test the binding by calling the start method.

    
    myPerson.start();
    
    

    When you build and run the app, you should see this:

    Welcome, Harry

    The name and the color of the name should change continuously.

Step 4: Adding the binding object as part of the activation process

Now we'll get more control over the lifetime of the Person object by instantiating and binding it in an activation handler and unbinding and destroying it in an unload handler.

  • You add the activated and unload event handlers as part of the WinJS.Utilities.ready function. This function is called immediately after he DOMContentLoaded event, which fires after the page has been parsed but before all the resources are loaded.

    
    
    var myPerson = new Person();
    
    WinJS.Utilities.ready(function () {
        WinJS.Application.addEventListener("activated", activatedHandler);
        WinJS.Application.addEventListener("unload", unloadHandler);
      }, false);
    
    function activatedHandler(e) {
        myPerson.bind("name", onNameChange);
        myPerson.bind("color", onColorChange);
        myPerson.start();
    }
    
    function onNameChange (newValue) {
        var span = document.getElementById("bindableSpan");
        span.innerText = newValue;
    }
    
    function onColorChange (newValue) {
        var span = document.getElementById("bindableSpan");
        span.style.color = newValue;
    }
    
    function unloadHandler(e) {
        myPerson.stop();
        myPerson.timeout = null;
        myPerson.unbind("name", onNameChange);
        myPerson.unbind("color", onColorChange);
        myPerson = null;
    }
    
    

Complete example

Here is the complete listing of the code in this topic.


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>ObjectBinding</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>

    <!-- ObjectBinding references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/default.js"></script>
</head>
<body>
    <div id="objectBinding">
        Welcome
        <span id="bindableSpan"></span>
    </div>
    <script type="text/javascript">
        var Person = WinJS.Class.define(
            function () {
                this._initObservable();
                this.name = "Harry";
                this.color = "blue";
                this.timeout = null;
            }, {

                _nameArray:
                    new Array("Sally", "Jack", "Hal", "Heather", "Fred", "Paula", "Rick", "Megan", "Ann", "Sam"),
                _colorArray:
                    new Array("lime", "lavender", "yellow", "orange", "pink", "greenyellow", "white", "lightblue", "lightgreen", "lightyellow"),

                _newName: function () {
                    this.setProperty("name", this._nameArray[this._randomizeValue()]);
                    this.setProperty("color", this._colorArray[this._randomizeValue()]);
                },
                
                _randomizeValue: function () {
                    var value = Math.floor((Math.random() * 1000) % 8);
                    if (value < 0)
                        value = 0;
                    else if (value > 9)
                        value = 9;
                    return value;
                },

                start: function () {
                    var that = this;
                    if (this.timeout === null) {
                        this.timeout = setInterval(function () { that._newName(); }, 500);
                    }
                },

                stop: function () {
                    if (this.timeout !== null) {
                        clearInterval(this.timeout);
                        this.timeout = null;
                    }
                }
            });

        WinJS.Class.mix(Person,
            WinJS.Binding.mixin,
            WinJS.Binding.expandProperties({ name: "", color: "" })
        );

        var myPerson = new Person();

        WinJS.Utilities.ready(function () {
            WinJS.Application.addEventListener("activated", activatedHandler);
            WinJS.Application.addEventListener("unload", unloadHandler);
        }, false);

        function activatedHandler(e) {
            myPerson.bind("name", onNameChange);
            myPerson.bind("color", onColorChange);
            myPerson.start();
        }

        function onNameChange (newValue) {
            var span = document.getElementById("bindableSpan");
            span.innerText = newValue;
        }

        function onColorChange (newValue) {
            var span = document.getElementById("bindableSpan");
            span.style.color = newValue;
        }

        function unloadHandler(e) {
            myPerson.stop();
            myPerson.timeout = null;
            myPerson.unbind("name", onNameChange);
            myPerson.unbind("color", onColorChange);
            myPerson = null;
        }
</script>
</body>
</html>


Related topics

Quickstart: Binding data and styles to HTML elements

 

 

Build date: 10/26/2012

Did you find this helpful?
(1500 characters remaining)
© 2013 Microsoft. All rights reserved.