Show Sidebar Menu

KoiDialogQuestion for User Choices and Command Handling

This article describes the KoiDialogQuestion component, which lets users choose between two commands via a dialog with a label and buttons. It explains how the component triggers a koi-operated event and propagates it through the DOM.

The purpose of the KoiDialogQuestion component is to provide the user with a choice between two commands.

The KoiDialogQuestion component consists of a label and two buttons. The label can display a question addressed to the user or a prompt for action. By clicking one of the buttons, the user issues the command associated with that button.

In many situations, the KoiDialogQuestion component can be substituted with the KoiSwitch component, which also enables the user to issue one of two commands. The key difference is that KoiSwitch initializes in a default position, preventing the user from issuing the corresponding command with a single click. To issue the default-position command, the user must first toggle to the other command and then back. In contrast, KoiDialogQuestion allows the user to immediately issue the chosen command.

Issuing a command triggers a koi-operated event. This event has its bubbles property set to true, allowing it to propagate up through the DOM tree. An external component that contains the KoiDialogQuestion component can listen for and respond to this event.

To determine which command the user selected, the external component should compare the event’s command code with the codes provided by the static methods getApplyActionCode and getCancelActionCode of the KoiDialogQuestion component.

The KoiDialogQuestion component not only emits the user-selected command but also handles it internally, implementing the KoiOperationsInterceptable behavior. It customizes the standard _stopPropagationWhenOperated method from KoiOperationsInterceptable to ensure that the command continues propagating through the DOM tree.

If command propagation needs to be stopped under specific conditions, a subclass of KoiDialogQuestion can override the _stopPropagationWhenOperated method.

Since KoiDialogQuestion listens to its emitted events, it can perform additional actions before the event leaves the component. For instance, it can extend the _updateSomethingWhenOperated method or implement the _handleOperated method. These methods might update the dialog's label, disable the buttons, or hide the dialog after the user has made a selection.

Class

The initialization process for the KoiDialogQuestion component is as follows:

  1. _onConstructed() KoiSocketConnectable
    • _constructState() KoiStateCapable
    • _constructSocket() KoiDialogQuestionSocketConnectable
  2. _onBeforeConnected() KoiSocketConnectable
    • _prepareSocket() KoiSocketConnectable
      • socket.getTemplate() KoiDialogQuestionSocket
  3. _onConnected() KoiElementStencil
    • _updateSomethingWhenConnected() KoiElementStencil
      • _updateOwnDataWhenConnected() KoiElementStencil
      • _updateStateCodeWhenConnected() KoiStateCapable
  4. _onAfterConnected() KoiElementStencil
    • isSomethingChanged() KoiStateCapable
    • _handleSomethingChangedWhenAfterConnected() KoiBaseControl
      • updateAppearance() KoiBaseControl
    • _setNothingChanged() KoiStateCapable
    • _subscribeToEvents() KoiOperationsInterceptable
      • _subscribeToOperateEvent() KoiOperationsInterceptable

The KoiDialogQuestion component is a subclass of KoiBaseControl and implements the behaviors KoiDialogQuestionSocketConnectable and KoiOperationsInterceptable.

The KoiDialogQuestionSocketConnectable behavior extends the functionality of KoiSocketConnectable by providing the component with a socket of the KoiDialogQuestionSocket class, which is responsible for displaying the message and the buttons (of the KoiIdButton class).

The KoiOperationsInterceptable behavior allows the component to respond to events triggered by its internal components, specifically the buttons. At the same time, the KoiDialogQuestion component modifies the _stopPropagationWhenOperated method to ensure that the event can propagate upward through the DOM tree without restrictions.

Data

The KoiDialogQuestion component does not manage or store its own data.

Attributes

id The component's identifier.
message The string displayed in the component.
apply_caption The label on the first button.
cancel_caption The label on the second button.
element_class The component's CSS class.

The component’s attributes include a main message, representing a question or prompt for the user, and labels for the buttons. These labels are static and cannot be modified after initialization. For dynamic label updates, you can create a subclass with the required functionality.

The element_class attribute is useful for assigning CSS classes to the component, such as when the dialog must be initially hidden and displayed later in response to a specific event.

State

The KoiDialogQuestion component does not have any additional visible states beyond those provided by the base KoiBaseControl class, which are controlled by the show and hide methods.

Nevertheless, it is possible to implement states that make the component more interactive. For example, a subclass could be created that, upon receiving a command from the user, sends the command in an event, changes the text of the message to a request to wait, disables the buttons, and waits for the result of the command execution before restoring the dialog’s functionality.

Event

The KoiDialogQuestion component triggers the koi-operated event in response to the user's choice. This event includes one of two command codes, as defined by the static methods getApplyActionCode and getCancelActionCode.

The koi-operated event has the property bubbles set to true, which causes it to propagate up the DOM tree. This feature allows buttons placed within a composite component to have their clicks automatically handled by the composite component acting as a controller.

In one example, clicking one of the dialog buttons triggers an event intercepted by the panel containing the dialog. The panel then updates the text of the KoiLabel component based on the command received from the event.

It’s important to note that the dialog is initially invisible and is displayed only after the external panel instructs its socket to make the dialog visible. However, hiding the dialog after the user makes a selection is not the panel's responsibility. Instead, the dialog hides itself as a reaction to the user’s action.

Displaying and hiding a dialog are typically considered opposite actions and are often assigned to the same controller. However, since dialogs can be created in unlimited numbers on a page, assigning their hiding behavior to the controller would require it to keep track of all the dialogs it has created. If the controller is only responsible for creating dialogs and they handle their own hiding, the controller no longer needs to manage their state. It can focus solely on its primary task: processing commands from the user.

Here’s another example where the KoiDialogQuestion component not only triggers an event but also reacts to it.

This example demonstrates how a dialog component can dynamically change its content based on the user's actions. In this case, the dialog modifies the text of the KoiLabel component, but it could also adjust button activity, add or remove internal components, offering greater flexibility for user interactions.

Usage

In many systems, a dialog is perceived as a panel that appears on the screen at specific moments to receive input from the user and then disappears. This perception leads to the following potential uses for dialogs:

  • Using a specialized dialog that is not recreated but remains hidden and is displayed as needed. For example, a file-save dialog.
  • Using a single dialog that is not recreated but remains hidden and is displayed as needed, with its text changing dynamically as required. For example, a dialog for deleting list items.
  • Using a large number of dialogs that are created and destroyed each time user input is needed.

In the first case, the dialog's text, button labels, and command codes are independent of context. Such dialogs are needed in small, limited quantities, are typically created immediately after the program starts, and are removed upon its termination. There is likely no need to implement them differently.

In the second case, the dialog must have a reinitialization method, allowing its content to change depending on the task. In this scenario, nearly all key components of the dialog—labels and commands—are modified. This results in the creation of an object that manages all possible configurations of the dialog’s content. Introducing such an object adds complexity to the system. Additional complexity arises in the components that handle events. Since the dialog becomes a multifunctional object, event handlers must interact with it on a more abstract level.

For example, if the same dialog asks whether to delete element X or element Y, instead of processing commands like “delete X,” “do not delete X,” “delete Y,” and “do not delete Y,” the handler must deal with abstract commands like “delete” and “do not delete,” supplemented with data containing the number or identifier of the element to be deleted.

To avoid unnecessary abstraction, I suggest using the third option, where narrowly specialized dialogs are created as needed.

However, I recommend predefining which of these dialogs might potentially be reused and which will not. For instance, a dialog for deleting an element might be reused as long as the element remains present on the page.