Standard components / Button

Try a working example of ButtonComponent and then see the code for the example.

A button is the most basic UI element you can probably think of, however in web apps it's largely implemented as some sort of secondary-class citizen - reacting to events properly, but not adjusting to various use cases that largely depend on the context. For example, it is often common to use button as a simple link instead of a form submit element, but it's also obvious it should behave the same way (as a button!) when it's just a link - that is, appear to be pressed. Or, perhaps, it should behave like a real button in some ways, but not others. To understand which features of the ButtonComponent are applicable in which cases it's better to do an overview of those features first, then learn how to use them, and then we can discuss situations in which those features can be applied.

Button states

While Webface.js lacks any kind of formal definition of "state", it is normally defined by component attributes, html attributes and, in particular, css classes assigned to a particular dom element.

Button has three important states it can be in:

  • Normal

    Means a button is clickable and will publish the click event if user clicks it.

  • Locked

    Means a button is temporarily made inaccessible due to some action, typically user clicking that button. In this case, a locked css class is added to the button's dom element.


    You can toggle between having this state on and off with behave("lock") and behave("unlock"). By default, on click event, ButtonComponent invokes behave("lock"). This default behavior can be disabled by setting writing button.set("lockable", false) (can also be done through data-lockable="false" attribute, it will update the corresponding ButtonComponent attribute automatically on initialization). Normally, in your css, you'd want to add styles to the button.locked selector, such that the button looks different from a normal one: for example has slightly less bright colors and a spinner is shown over the button, indicating that some processing is being performed.

    webface_rails gem provides css styles for buttons along with the rest of the stylesheets for all of Webface.js standard components.


    Suppose your button doesn't invoke any actions that require some significant time to process - such as http requests or cryptographic algorithms - and it's potentially ok (and even expected) that users click it multiple times. For instance, if you have a form to purchase tickets for an event, it is possible that buyers would want to purchase multiple tickets for different people - we cannot predict how many, so we would add a button saying "Add attendee", which would add a row of form fields that are required for each attendee. In this case, it makes no sense to lock the button because adding new form fields is done very fast. The button, of course, would not be adding the fields itself, but merely publishing the click event, while its parent - our custom form component of some sort, would capture the event and we'll write some code that would process this event. All the while, the only thing we'd need to do is add a simple html-attribute to the button's dom element:

    We won't need to change anything in ButtonComponent for this to work.
  • Disabled

    Means a button is not supposed to be clicked at all - typically because some condition, such as required form fields not being filled - is not satisfied.

    • Usage

      This state is defined by the disabled attribute which can be set with both Javascript code and also in html by adding disabled="disabled" to the button's dom element.

      Note how the previous "Locked" state didn't have a corresponding attribute in ButtonComponent. .lockable is a setting that affects locking the button, but not the state itself. And having the locked attribute is not actually necessary - we just add or remove button dom element's css class in ButtonComponentBehaviors to accomplish our goal. But with disabled there is a component attribute we can (and should) change with ButtonComponent.set("disabled", [true/false])

      To disable/enable the button, please use the component's attribute setter (instead of behaviors) like this:

      button.set("disable", true);

      If you use behaviors instead, the button may appear disabled for users, but the value of the component's attribute will remain unchanged, which may affect your code.

The click event and its handler

The most common thing people do to a button is click it (or tap it, which highly depends on one's sexual preferences). Thus, the handler for this behavior has a number of things worth discussing:

  • Event lock is set to the click event whenever a button is clicked (unless the lockable attribute was previously set to false. If button is locked, either after it was clicked or because we locked it programmatically, it will not process any further click events until it is unlocked. You MUST unlock it with ButtonComponent.behave("unlock") manually from your code when you want to be back to processing new click events again - there's currently no default event handler which does it for you (because there's no reason for it).
  • You can prevent browser from invoking its default handler for your button click event by setting prevent_native_click_event attribute to true. This is useful in forms, for example, when you don't want to immediately submit a form, but rather validate it in the frontend and only submit that form after all validations pass. The default browser handler for the submit button, in this case, is submitting the form. We disabled this handler, while still instructing Webface.js to run our own handler code. This is so common (as buttons are mostly used in forms) that ButtonComponent defaults to preventing native browser event handler for the click event for all of its instances. However, it is also desirable to enable default browser handler when a button acts as a link. It can be done by adding an appropriate html-attribute:

    If you're using webface_rails, there's a special helper to generate buttons that act as links: button_link. See Ruby On Rails integration / Standard components views for more info.

    If you're not using webface_rails, don't forget to set data-prevent-native-click-event="false" on the submit buttons (if that's indeed what you want). TODO: perhaps the default attribute setting should be changed to data-prevent-naive-click-event="false" to avoid confusion, while setting the attribute value to true for all buttons that are not links in webface_rails.