WinJS mixins

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

Mixins are objects that implement a certain class of functionality. For example, in the Windows Library for JavaScript there are mixins that manage events and mixins that handle binding.

Mixins aren't designed to be used directly, but you can use them to add functionality to your types. Mixins contain implemented functions that can be added to many types.

You can create your own mixins. This code shows how to define a Movable mixin that contains functions goForward, goBackward, turnLeft, and turnRight and use WinJS.Class.mix to add it to the Robot class.

var Robot = WinJS.Class.define(function (name) {
    this.name = name;
});

var Movable = {
    direction: "stopped",
    goForward: function () { this.direction = "going forwards" },
    goBackward: function () { this.direction = "going backwards" },
    turnRight: function () { this.direction = "turning right" },
    turnLeft: function () { this.direction = "turning left" },
};

WinJS.Class.mix(Robot, Movable);

WinJS.Namespace.define("Robotics", {
    Robot: Robot
});

var myRobot = new Robotics.Robot("Mickey");

myRobot.goBackward();

console.log(myRobot.direction);
// Output: "going backwards"

Using WinJS mixins

You can use WinJS.Utilities.eventMixin and WinJS.UI.DOMEventMixin to add event management functionality, and WinJS.Binding.dynamicObservableMixin to add binding management functionality.

Adding WinJS.Utilities.eventMixin to a type

You can add WinJS.Utilities.eventMixin to any type you define. It contains WinJS.Utilities.eventMixin.addEventListener, WinJS.Utilities.eventMixin.removeEventListener, and WinJS.Utilities.eventMixin.dispatchEvent functions that help you raise and handle custom events that you define on the type.

For example, the following code shows how to define a type Robot with a rename event that is raised whenever the name of the Robot is changed. The event handler writes new output to the JavaScript Console in Microsoft Visual Studio.

var Robot = WinJS.Class.define(function (name) {
        this._name = name;
    }, {
        name: {
            get: function () {
                return this._name;
            },
            set: function (newName) {
                this._name = newName;
                this.dispatchEvent('rename');
            }
        }
});

WinJS.Class.mix(Robot, WinJS.Utilities.eventMixin);
WinJS.Class.mix(Robot, WinJS.Utilities.createEventProperties("rename"));

var rob = new Robot("Bob");

robot.addEventListener("rename", function () {
    console.log("Robot renamed to " + this.name);
}.bind(robot));

robot.name = "Jim";
// Output: "Robot renamed to Jim"

In this code, you mix the Robot type with WinJS.Utilities.eventMixin to get the event listener functionality, and you also mix the WinJS.Utilities.createEventProperties function to define the event. Note that you must mix the event mixin with the type before you use WinJS.Utilities.createEventProperties. When you define the name property, you use the WinJS.Utilities.eventMixin.dispatchEvent function in the set accessor to raise the rename event.

Adding DOMEventMixin to a type

WinJS.Utilities.eventMixin is useful for defining events on types that are dealt with completely in JavaScript. It isn't useful when you're working with events that are associated with DOM elements. WinJS controls wrap and manipulate HTML elements. These controls often contain events that are based on the DOM events raised from their associated DOM elements. For example, when you use a DatePicker, you find it easier to respond to a change event from the DatePicker control rather than to track individual change events from the three select controls.

Associating events with the control type rather than the DOM element also protects the code from changes, for example if the implementation of the DatePicker changes the controls it contains.

The DOM event model allows for event propagation. DOM events are propagated up the DOM tree and can be handled at any level. This is useful when you have a lot of clickable elements. For example, you can put a single click handler function on the DIV element that contains the elements and then process all the click events from all the contained elements as they bubble up. For more information about DOM event handling, see Event capture and event bubbling.

WinJS.UI.DOMEventMixin contains methods that implement events that propagate up through the DOM tree. It has three functions: addEventListener, removeEventListener, and dispatchEvent.

To add this mixin to a type you have created, you must set a property named _domElement on the type. This is the field that the WinJS.UI.DOMEventMixin implementation looks for when it raises the event. It becomes the target node for the event.

The following code shows how to create a minimal control class on a DIV element and mix WinJS.UI.DOMEventMixin. You can then add an event listener for the click event and respond to it.

For this code to work, you need one DIV that has an ID of "div" and a second DIV that has an ID of "report".

var MyButton = WinJS.Class.define(function (elem) {
                    this._domElement = elem;
                 elem.winControl = this;
                 this._numberClicks = 0;
    },
    {
        initialize: function () {

            this._domElement.appendChild(document.createElement('button'));

            function clickHandler(ev) {
                var clicks = ++this._numberClicks;
                document.getElementById("report").innerText = clicks;
            }
            this._domElement.querySelector('button').addEventListener("click", 
                                                    clickHandler.bind(this));
        }
});

WinJS.Class.mix(MyButton, WinJS.UI.DOMEventMixin);

var button = new MyButton(document.getElementById("div"));
button.initialize();;

Adding binding functionality with WinJS.Binding.mixin

To bind a user-defined object to an HTML element, you must make it observable, that is, capable of notifying listeners when its properties change. The WinJS.Binding.mixin provides this functionality. For an example, see How to bind a complex object.