Language: HTML | XAML

Quickstart: adding HTML controls and handling events (HTML)

Applies to Windows and Windows Phone

Every app needs controls, such as buttons, check boxes, and drop-down lists. Windows Runtime apps using JavaScript can use two types of controls: intrinsic HTML controls and Windows Library for JavaScript controls. Intrinsic HTML controls are those controls, such as buttons and check boxes, that are a part of the HTML standard.

Here we focus on how to create and use HTML controls. The next topic, Quickstart: Adding WinJS controls and styles, describes how to create and use WinJS controls.

(Windows only) See this feature in action as part of our App features, start to finish series:  User interaction: Touch input... and beyond and Windows Store app UI, start to finish.

Prerequisites

What is a control?

In many application programming models, you need a control to display or interact with content. Because most HTML elements are capable of displaying content and responding to a variety of events, the distinction between a control and an element isn't always clear for Windows Runtime apps using JavaScript. We refer to elements and objects whose primary purpose is to provide interactivity as controls. For a list of elements and objects that fall into this category, see Controls by function.

Adding an HTML control

You can use any HTML control in your Windows Runtime app using JavaScript.

Hh465402.wedge(en-us,WIN.10).gif To add an HTML control

  • To add an HTML control, just add the control's HTML to your page, like you would for a typical web page. This example creates a button:
    
    <button id="button1">An HTML Button</button>
    
    

    It's generally a good idea to assign an ID or class name to your control so that you can easily retrieve and manipulate it. Later, when we show you how to attach events, you'll use the button's ID to find the button.

The HTML for a control isn't always as straightforward as it is for a button. For example, to create a slider control, you use the input input element:


<input type="range" />

For a list of available HTML controls and the markup you use to create them, see the Controls list.

Handling events

Every control provides events that enable you to respond to actions from the user. For example, the button control provides a click event that is raised when a user clicks the button. You create a function, called an event handler, to handle the event and then you register the event handler with the control.

There are two ways to register an event handler. One way is to add an event handler in your HTML by setting the control's event attribute to the name of a JavaScript event handler function or a JavaScript statement. For more info about this approach, see the Why you shouldn't set an event handler in markup section.

The other way to add an event handler is to add it programmatically. This is the approach we recommend.

Hh465402.wedge(en-us,WIN.10).gifTo register an event handler programmatically

  1. Create the control and assign it an ID. This example creates a button and gives it the ID "button1".
    
    <button id="button1">An HTML button</button>
    
    
  2. Just for this example, create a paragraph element and assign the ID "button1Output". You'll use it to display info about the button's click event.

    
    <p id="button1Output"></p>
    
    
  3. In your JavaScript code, define an event handler. Most event handlers take a single argument, an Event object that contains info about the event. Other events might return other types of event info objects that provide info specific for that event.

    The click event provides a MouseEvent object that contains info about the event, such as which mouse button was pressed and which object fired the event. This example creates a click event handler that uses the MouseEvent object to obtain the x- and y-coordinates of the point that the user clicked.

    (The click event also responds to touch and keyboard interaction. The examples in this topic assume that the user is clicking with a mouse. For more info about interacting with touch and different devices, see Responding to user interaction.)

    
    function button1Click(mouseEvent) {
        var button1Output = document.getElementById("button1Output");
        button1Output.innerText =
        mouseEvent.type
        + ": (" + mouseEvent.clientX + "," + mouseEvent.clientY + ")";
    
    }
    
    
  4. Now you need to attach the event to your control by retrieving it and calling addEventListener. The question is, when should you retrieve the control? You could just add it anywhere to your JavaScript code, but then there's a chance it might get called before the control exists.

    • If you're adding the control to your app's start page, which is defined by default.html and default.js, use the WinJS.UI.processAll function to register your event handlers. Each Microsoft Visual Studio template creates a default.js file that calls WinJS.UI.processAll in the activated event handler. Because it's an asynchronous method, the WinJS.UI.processAll method returns a Promise. To attach your event handlers, provide a then or done function for the Promise that WinJS.UI.processAll returns and use that function to attach your event handlers. (For more info about promises, see Asynchronous programming in JavaScript.)

      This example uses WinJS.UI.processAll to attach the button's event handler.

      
      (function () {
          "use strict";
      
          var app = WinJS.Application;
          var activation = Windows.ApplicationModel.Activation;
          WinJS.strictProcessing();
      
          app.onactivated = function (args) {
              if (args.detail.kind === activation.ActivationKind.launch) {
                  if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                      // TODO: This application has been newly launched. Initialize
                      // your application here.
                  } else {
                      // TODO: This application has been reactivated from suspension.
                      // Restore application state here.
                  }
                  args.setPromise(WinJS.UI.processAll().done(function () {
                      var button1 = document.getElementById("button1");
                      button1.addEventListener("click", button1Click, false);
                      })
                  );
              }
          };
      
          app.oncheckpoint = function (args) {
              // TODO: This application is about to be suspended. Save any state
              // that needs to persist across suspensions here. You might use the
              // WinJS.Application.sessionState object, which is automatically
              // saved and restored across suspension. If you need to complete an
              // asynchronous operation before your application is suspended, call
              // args.setPromise().
          };
      
          // The click event handler for button1
          function button1Click(mouseEvent) {
              var button1Output = document.getElementById("button1Output");
              button1Output.innerText =
                  mouseEvent.type
                  + ": (" + mouseEvent.clientX + "," + mouseEvent.clientY + ")";
      
          }
      
          app.start();
      })();
      
      
      

      For more info about the WinJS.UI.processAll method, see Quickstart: adding WinJS controls and styles.

    • If you're adding your control to a Page control, use the Page control's ready function to attach your event handlers.

      The WinJS Page control provides a way to divide your content into modular, reusable units. Your app might contain one or more Page controls automatically, depending on which Visual Studio template you used to create it.

      When you create a Page control, it automatically includes a ready function that you can use to add an event handler for your button. This example shows the complete JavaScript code for a Page control that adds a click event handler to a button.

      
      
      // home.js
      (function () {
          "use strict";
      
          WinJS.UI.Pages.define("/pages/home/home.html", {
              // This function is called whenever a user navigates to this page. It
              // populates the page elements with the app's data.
              ready: function (element, options) {
                  // TODO: Initialize the page here.
                  var button1 = element.querySelector("#button1");
                  button1.addEventListener("click", this.button1Click, false);
              },
      
              button1Click: function(mouseEvent) {
                  var button1Output = document.getElementById("button1Output");
                  button1Output.innerText =
                  mouseEvent.type
                  + ": (" + mouseEvent.clientX + "," + mouseEvent.clientY + ")";
      
              }
          });
      })();
      
      
      

      For more info about Page controls, see Adding Page controls.

    • If you're adding the control to your own custom HTML and JavaScript files, handle the DOMContentLoaded event and use it to call WinJS.UI.processAll. You can register for the DOMContentLoaded event anywhere in your code, because the document object already exists by the time your code executes. Provide a then or done function for the Promise returned by WinJS.UI.processAll and use that function to attach your event handlers.

When you run the app and click the button, it displays the coordinates of the click point.

Why you shouldn't set an event handler in markup

You can add event handlers in your markup, but in some ways it can be more complicated than adding them with the addEventListener method because of scoping issues. When you use Visual Studio to create a new Windows Runtime app using JavaScript Blank Application, it creates this default.js file:


(function () {
    "use strict";

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;
    WinJS.strictProcessing();

    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            args.setPromise(WinJS.UI.processAll());
        }
    };

    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. You might use the
        // WinJS.Application.sessionState object, which is automatically
        // saved and restored across suspension. If you need to complete an
        // asynchronous operation before your application is suspended, call
        // args.setPromise().
    };

    app.start();
})();

All code is wrapped in an anonymous global function. Wrapping your code in an anonymous global function is a good coding practice because it limits the scope of your code and avoids polluting the global namespace. If you add the event handler described earlier, the code behind file looks like this:


(function () {
    "use strict";

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;
    WinJS.strictProcessing();

    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            args.setPromise(WinJS.UI.processAll());
        }
    };

    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. You might use the
        // WinJS.Application.sessionState object, which is automatically
        // saved and restored across suspension. If you need to complete an
        // asynchronous operation before your application is suspended, call
        // args.setPromise().
    };

    function button1Click(mouseEvent) {
        var button1Output = document.getElementById("button1Output");
        button1Output.innerText =
        mouseEvent.type
        + ": (" + mouseEvent.clientX + "," + mouseEvent.clientY + ")";

    }

    app.start();
})();

If you set the event handler in markup instead of in your code, the button from the earlier examples would look like this:



<!-- Incorrect code. Do not use this in your solution. -->
<button id="button1" onclick="button1Click(event)">An HTML button</button>

When you run the app and click the button, nothing happens. That's because the button1Click function is wrapped in an anonymous function and isn't directly accessible to your markup. For your code to work, you'd need to move button1Click outside the anonymous function.


(function () {
    "use strict";

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;
    WinJS.strictProcessing();

    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            args.setPromise(WinJS.UI.processAll());
        }
    };

    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. You might use the
        // WinJS.Application.sessionState object, which is automatically
        // saved and restored across suspension. If you need to complete an
        // asynchronous operation before your application is suspended, call
        // args.setPromise().
    };

    app.start();
})();

function button1Click(mouseEvent) {
    var button1Output = document.getElementById("button1Output");
    button1Output.innerText =
    mouseEvent.type
    + ": (" + mouseEvent.clientX + "," + mouseEvent.clientY + ")";

}


But now button1Click is global, which is not what we want. A better approach is to move the button1Click definition back inside the anonymous function and then use WinJS.Namespace.define to make it publicly accessible (for an example of how to do this, see How to set event handlers declaratively).

Remarks

Don't use JavaScript URIs

Don't use JavaScript URIs in your event handler because your app won't execute them. For example, if you try this, nothing happens when you click the button:



<!-- Incorrect code. Do not use this in your solution. -->
<button id="button1" onclick="javascript: 2 + 2;">An HTML Button</button>

This restriction applies to code in the app's local context (code included in your app package), but doesn't apply to code on external web pages accessed by your app.

Using forms

In a traditional HTML website, controls and other input elements are usually contained in a form element. form elements are used to pass data to the server. Because most programming for a typical app is client-based, you don't usually need to use a form element.

Using transparent layers

It's common practice to use a full screen transparent layer, such as an empty div element, to detect certain user interactions or to display animations. However, covering an HTML control with a transparent layer can make it less responsive to user interaction. To keep your HTML controls responsive, don't put a transparent layer over them.

Summary and next steps

You learned how to create HTML controls and how to attach event handlers.

Next, learn how to use the new WinJS controls provided for Windows Runtime apps using JavaScript by reading Quickstart: adding WinJS controls and styles.

To learn more about specific controls, see the Controls list.

Samples

Related topics

Coding basic apps
Quickstart: adding WinJS controls and styles
Controls list

 

 

Show:
© 2014 Microsoft