Skip to content

Client side components

Mark Reeves edited this page Jan 3, 2018 · 3 revisions

This page discusses the design approach to widgets on the client side and is primarily useful for people wishing to understand how WComponents works on the client either out of curiosity, the need to debug or to work on WComponents client side code.

Truth in DOM - Stateless Javascript

Client side components avoid storing state. Instead the DOM is the source of truth and javascript widget controller modules know how to read and write state for their particular widget in the DOM. These widget controllers are singleton instances which respond to user interaction.

A simple example is wc/ui/printButton. It listens to all clicks in the document and performs an action if a "print button" has been clicked (yes, print buttons are silly, but it is a nice simple example).

Simplified Example

The code sample below provides a simple example of implementing a print button.

define([
  "wc/dom/event",
  "wc/dom/initialise",
  "wc/dom/Widget",
  "wc/dom/shed"],
  function(event, initialise, Widget, shed) {
    "use strict";

    /**
     * This is the singleton constructor, we could also
     * use object literal notation but that always ends
     * up not scaling well.
     * @constructor
     */
    function PrintButton() {
      /* define a Print Button as an element with
       * a tagName of "button" and the css class "wc-printbutton"
       */
      var PRINT = new Widget("button", "wc-printbutton");

      /**
       * Click listener to invoke the print dialog.
       * @param {Event} $event The click event.
       */
      function clickEvent($event) {
        var element;
        // Has the event been cancelled by another controller?
        // If not, is the click inside a Print Button? If so,
        // has it been disabled?
        if (!$event.defaultPrevented &&
          (element = PRINT.findAncestor($event.target)) &&
          !shed.isDisabled(element)) {
          // A click on a Print Button which is not disabled
          $event.preventDefault();
          // "do stuff"
          window.print();
        }
      }

      /**
       * When the page is ready, add a click listener
       * to the document body.
       * @param {Element} element The element being
       *   initialised: document.body.
       */
      this.initialise = function(element) {
        // listen to click events on the document body
        event.add(element, event.TYPE.click, clickEvent);
      };
    }

    // create a singleton instance
    var instance = new PrintButton();
    // register with the initialise lifecycle
    // (see "Lifecycle on client side" wiki page)
    initialise.register(instance);
    // return our singleton to the AMD loader
    // (so it can be "required" - not likely for this controller)
    return instance;
});
Clone this wiki locally