Show Sidebar Menu

KoiTable Display Tabular Data with Web Components

This article explains the KoiTable and KoiConnectedTable components in the KoiCom library. It covers how they display tabular data, with KoiTable using its own data and KoiConnectedTable updating based on external data.

The purpose of the KoiTable component is to display an array of values in a structured format within the interface.

The data is represented as a two-dimensional array, where the first row serves as a header containing column names. This format is similar to how data is stored in a CSV file.

A table of the KoiTable class displays its own data, which it receives through a tag attribute. Since the value of a tag attribute can only be a string, the two-dimensional array is converted to a string using encodeURIComponent and JSON.stringify. This transformation is performed using the convertToAttribute static methods implemented for the KoiDataElementList class.

Most often, the table component is not used to display its own data but rather to display data from a provider. For this purpose, the KoiConnectedTable component is used.

In the example below, the table on the right is a KoiConnectedTable component. Its provider is the table on the left. When the state or own data of the left table changes, it triggers the koi-changed event, to which the right table responds. For the left table to trigger the koi-changed event, it implements the KoiChangedEventDispatchable behavior. For the right table to respond to this event, it implements the KoiControlListDataConnectorInteractable behavior.

When displayed, table components can format the values being displayed based on the received data, accept input data in formats other than a two-dimensional array, and add buttons or other control components to table rows.

In the example above, the right table reacts to the koi-changed event by retrieving data from the left table and summing it by columns, forming new displayed data.

A filterable table component can also be created based on the table. This component displays data from a provider while filtering it based on its own data.

Class

The initialization process for the KoiConnectedTable component is as follows:

  1. _onConstructed() KoiConnectorInteractable
    • _constructState() KoiStateCapable
    • _constructSocket() KoiTableSocketConnectable
    • _constructConnector() KoiSingleConnectorInteractable
    • _prepareConnector() KoiConnectorInteractable
  2. _onBeforeConnected() KoiSocketConnectable
    • _prepareSocket() KoiSocketConnectable
      • socket.getTemplate() KoiTableSocket
  3. _onConnected() KoiElementStencil
    • _updateSomethingWhenConnected() KoiElementStencil
      • _updateOwnDataWhenConnected() KoiConnectorInteractable
        • _getConnectorEventDetail() KoiConnectorInteractable
        • _setOwnDataInitialValueBasedOnConnectorEvent() KoiConnectorInteractable
          • _getConnectorDataFromEvent() KoiConnectorInteractable
          • _setOwnDataInitialValueBasedOnConnectorData() KoiConnectorInteractable
      • _updateStateCodeWhenConnected() KoiStateCapable
        • _determineStateCode() KoiConnectorInteractable
        • _setStateCode() KoiStateCapable
  4. _onAfterConnected() KoiElementStencil
    • isSomethingChanged() KoiStateCapable
    • _handleSomethingChangedWhenAfterConnected() KoiBaseControl
      • updateAppearance() KoiBaseControl
      • _setNothingChanged() KoiStateCapable
      • _subscribeToEvents() KoiConnectorInteractable

During the _onConstructed phase, the component creates a connector. This connector can modify the component’s own data during the _onConnected phase and affect the data display during the _onAfterConnected phase.

This initialization process is the same for components with or without their own data. However, updating the component’s display requires the isSomethingChanged method to return true. Since the KoiConnectedTable component does not have its own data, it invokes the this._state.setChanged() method each time the connector's data changes to ensure the data is displayed in the socket.

If the provider is not ready to supply data during the component’s initialization, the component initializes with a loading state. Later, when the provider triggers the koi-changed event, the component responds to this event through the connector and calls the _attemptApplyConnectorDataChanged handler.

_attemptApplyConnectorDataChanged() KoiConnectorInteractable
  • _updateSomethingWhenConnectorDataChanged() KoiConnectorInteractable
    • _updateOwnDataWhenConnectorDataChanged() KoiConnectorInteractable
    • _updateStateCodeWhenConnectorDataChanged() KoiConnectedTable
      • _determineStateCode() KoiConnectorInteractable
      • _setStateCode() KoiStateCapable
      • _state.setChanged() KoiState
  • _onAfterConnectorDataChanged() KoiConnectorInteractable
    • isSomethingChanged() KoiStateCapable
    • _handleSomethingChangedWhenConnectorDataChanged() KoiControlConnectorInteractable
      • _dispatchChangedEventWhenConnectorDataChanged() KoiConnectorInteractable
      • _updateAppearance() KoiBaseControl

Note the presence of the _updateOwnDataWhenConnectorDataChanged method. This method is empty. If a subclass of the component implements the KoiDataCapable behavior, it can override this method to update its own data based on the connector’s data.

Additionally, the basic version of the KoiConnectedTable component does not dispatch events, meaning the _dispatchChangedEventWhenConnectorDataChanged method is also empty. If a subclass implements the KoiChangedEventDispatchable behavior, it should consider calling the _dispatchChangedEvent method within _dispatchChangedEventWhenConnectorDataChanged.

Both the initialization process and the process of handling provider data changes lead to the invocation of the _updateAppearance method, which updates the component's display.

The _updateAppearance method operates in two stages. The first stage occurs in the _beforeDisplayNormalState method, which runs once when the provider is first ready to supply data. At this stage, the table’s header is rendered using the first row of data. The second stage occurs every time the provider updates its data, during which the table's body is redrawn.

_updateAppearance() KoiBaseControl
  • isStateAbnormal() KoiStateCapable
  • _beforeDisplayNormalState() KoiSocketConnectable
    • _displaySocket() KoiTableStencil
      • _displayHead() KoiTableStencil
        • _getDataToDisplayInHead() KoiTableStencil
          • _getDataToDisplayInSocket() KoiConnectedTable
          • _convertDataToHeadData() KoiConnectedTable
        • _displayDataInHead() KoiTableSocketConnectable
  • _displayNormalState() KoiSocketConnectable
    • _updateSocket() KoiTableStencil
      • _displayBody() KoiTableStencil
        • _getDataToDisplayInBody() KoiTableStencil
          • _getDataToDisplayInSocket() KoiConnectedTable
          • _convertDataToBodyData() KoiConnectedTable
        • _displayDataInBody() KoiTableSocketConnectable

This process separates the table’s header from its body. When the connector’s data changes, the header is defined once and does not change thereafter. The process assumes that the number of table columns remains constant when the data changes. However, if the header needs to be redrawn, the component’s default behavior can be overridden in subclasses.

For both the header and the body, data is provided through the KoiControlListDataConnectorInteractable behavior using the _getItemsFromConnectorData method. The component then converts the received data into arrays that the table socket can display. This conversion is performed by the _convertDataToHeadData and _convertDataToBodyData methods.

In the example above, the table on the right uses the conversion methods to sum the received data by columns.

Attributes

id Component identifier
provider_id Provider identifier

The provider_id attribute specifies the identifier of the provider component that serves as the data source for the table. The provider's identifier is read once during the component's creation. If the provider is ready to supply data at the moment of the component's creation, the table is rendered immediately. If not, attempts to render the table are made with each koi-change event from the provider.

State

Similar to KoiLabel, the KoiTable and KoiConnectedTable components implement only the display states defined in the base class KoiBaseControl. These states are managed using the show and hide methods provided by the KoiDisplayable behavior. However, unlike KoiLabel, which reacts to the model's state by implementing methods with the display prefix (e.g., _displayError), the base KoiTable component does not implement such methods. If you need to display specific states caused by data errors, you should create a subclass of KoiTable capable of handling and displaying these states appropriately.

In the example above, both tables implement the _displayError and _displayWaiting methods, where they hide the component using the hide method. Alternatively, you could implement other approaches, such as showing a loading indicator or an error message.

Additionally, it is often necessary to represent an additional state indicating the absence of data to populate the table rows. For example, this could occur when a user requests unavailable data or after filtering results in no data to display. This behavior is also not implemented in the KoiTable class and must be handled in a subclass.

Event

It is assumed that the KoiConnectedTable does not have its own data. While there may be cases where a table component with its own data is required, it is more common for the table to display external data. Therefore, there is no reason for the table to trigger the koi-changed event.

Descendants of the KoiConnectedTable component can implement the KoiChangedEventDispatchable behavior if necessary. This allows them to trigger events when data or state changes occur. In such cases, you should consider invoking the event within the _dispatchChangedEventWhenConnectorDataChanged method.

Usage

The KoiConnectedTable component is a straightforward and basic tool for displaying tabular data. When the data is updated, the component redraws all its rows entirely. It does not support redrawing individual rows, making it inefficient for displaying a large number of rows.

However, it is not recommended to create a descendant of KoiConnectedTable that can redraw rows individually. A better approach would be to implement a component based on KoiCompositeSocket, where row management is built using an array of references to individual row components.

On the other hand, the KoiConnectedTable component can serve as a solid foundation for creating tables, lists, galleries, or other components that display structured or enumerated data in various formats.

Additional features such as pagination and filtering components can be added to these components. Further details will be provided in the corresponding sections of the documentation.