A component for selecting one of two possible values.
Do not confuse KoiFormFieldBinary with KoiSwitch. While these components may use the same native internal checkbox element, which makes them visually similar, KoiFormFieldBinary serves a different purpose. It is an input field rather than a control component.
The purpose of KoiFormFieldBinary is identical to that of KoiFormFieldString. It provides users with a means to modify a dataset through an input field, initializes the field with a default value, accepts a new value from the user, and emits this value via the koi-form-field-change event.
Like any other input field, KoiFormFieldBinary can display notifications to users about the completeness and validity of the entered data.
The main difference from KoiFormFieldString and similar input fields is that KoiFormFieldBinary operates exclusively with two value options. When a user interacts with KoiFormFieldBinary, the component toggles its value between these two options.
Class
The initialization process for the component is as follows:
-
_onConstructed() KoiDataCapable
- _constructState() KoiStateCapable
- _constructData() KoiFormFieldBinaryDataCapable
- _constructSocket() KoiFormFieldNativeSwitchSocketConnectable
- _constructInnerNativeComponentData() KoiNativeInputDataCapable
-
_onBeforeConnected() KoiDataCapable
- _constructFormFieldChangedEvent() KoiFormFieldChangedEventDispatchable
- _prepareDefaultDataValuesFromAttributes() KoiFormFieldBinaryDataCapable
-
- data.setDefaultValuesFromAttributes() KoiData
- _prepareDataOptionsFromAttributes() KoiFormFieldBinaryDataCapable
- _prepareSocket() KoiSocketConnectable
-
- socket.getTemplate() KoiFormFieldNativeSwitchSocket
-
- socket._getTemplateForInput() KoiFormFieldNativeSwitchSocket
- socket._getLabelTemplate() KoiFormFieldNativeSwitchSocket
- socket._getErrorHolderTemplate() KoiFormFieldBaseSocket
-
_onConnected() KoiElementStencil
- _updateSomethingWhenConnected() KoiElementStencil
-
- _updateOwnDataWhenConnected() KoiElementStencil
- _updateStateCodeWhenConnected() KoiStateCapable
-
_onAfterConnected() KoiElementStencil
- isSomethingChanged() KoiDataCapable
- _handleSomethingChangedWhenAfterConnected() KoiBaseControl
-
- _updateAppearance() KoiBaseControl
- _setNothingChanged() KoiDataCapable
- _subscribeToEvents() KoiOperationsInterceptable
-
- _subscribeToOperateEvent() KoiOperationsInterceptable
The KoiFormFieldBinary component inherits from KoiFormFieldStencil and follows a similar initialization chain to other input fields.
It implements the KoiFormFieldBinaryDataCapable behavior, which defines that the component uses its internal data of type KoiFormFieldBinaryData.
This data object differs slightly from the data objects of other input fields due to the implementation of the KoiBinary behavior. This behavior restricts the value of the data element to two options between which the value can toggle.
These options are extracted from the component’s attributes in the _prepareDefaultDataValuesFromAttributes method of the KoiFormFieldBinaryDataCapable behavior. To achieve this, the component extends the method with a call to _prepareDataOptionsFromAttributes.
Next, the component uses its internal data values in the _displaySocket method to initialize the socket. Instead of passing its actual data value to the socket, the component provides information on whether the value corresponds to the first or second option. The details of this process are implemented in the _convertDataToInitialSocketSettings method. Let's explore why this is necessary.
As noted in the descriptions of other input components, native components do not emit their values through events. Therefore, KoiFormFieldBinary must implement the KoiNativeInputDataCapable behavior, which adapts native component interactions to the managed component workflow. This behavior enables the component to receive a command to modify its data based on user interaction.
However, unlike other input fields, which directly obtain values from the socket's native input field, the socket used by KoiFormFieldNativeSwitchSocket differs. It does not receive a specific value from the user.
In the case of a native checkbox component, the situation becomes more complex because user interaction toggles the component's state rather than explicitly setting a value. One state is conventionally represented by true and the other by false. Thus, the socket containing such a native component does not inherently know which value the user has selected.
The only information the component can provide to the socket is the state it should adopt during initialization. This explains the unique implementation of the _convertDataToInitialSocketSettings method mentioned earlier.
Additionally, the only feedback the socket can provide to the component is its current state. The component retrieves this state using the _getCheckedFromSocket method, implemented in the KoiFormFieldNativeSwitchSocketConnectable behavior. It then converts the state information into one of the two possible values using the _getOperationDataFromEvent method and uses the resulting value to form a "set value" command.
By implementing the KoiOperationsInterceptable behavior, the component processes this command in the _applyOperationToOwnData method, updates its internal data, and subsequently triggers the koi-form-field-change event.
Thus, the component encapsulates its internal implementation details and behaves like any other input field externally. It emits a standard event and provides a typical data object through this event.
As with all other input fields, it is worth emphasizing that the component does not directly alter the state of the internal component or provide methods for doing so. Full control of the checkbox state is delegated to the user. The component reacts to user actions by updating its internal data and emitting the koi-form-field-change event.
Data
The internal data of the KoiFormFieldBinary component is of type KoiFormFieldBinaryData and is defined by the following schema:
What sets the KoiFormFieldBinaryData object apart from KoiFormFieldData is the implementation of the KoiBinary behavior. This behavior specifies that the data element field_value can take one of two possible values, defined by the properties primary_option and secondary_option.
Usually, a data element that accepts two possible values is encoded as a Boolean variable. However, this approach has some drawbacks.
The first issue is that from the value true or false, it is impossible to understand the intended meaning. For instance, the statement "memory=true" does not clarify what is implied. It could mean "memory is enabled," "memory is present," or "memory will be used in the process." Using a value of a different type, such as a string, allows not only the state to be represented but also the context in which the state is significant.
The second issue is the potential to encounter a third value, such as "unknown." In certain contexts, such a value should raise an error. However, if the erroneous value is not preserved in the data object, describing such an error becomes impossible. A system that discards erroneous values cannot continue functioning while processing the error. Conversely, a system that retains the erroneous value can notify the user of the error and, by processing the value in some manner, continue functioning as expected.
With a KoiFormFieldBinaryData object, any value received by the data element will be preserved. This allows the implementation of comparison methods to validate the received value against the predefined options during the validation process.
Connector
The initial value and possible options for the component are determined from the tag attributes.
An alternative method to define initial values for the component's data is by obtaining them through a connector to a data provider. This is achieved by using the KoiControlConnectorInteractable behavior and specifying the provider’s identifier in the component’s provider_id parameter.
Direct connections of a component to a data provider for string or numeric values are rarely used. Typically, the provider is connected not to individual input fields but to a form, which generates the input fields and passes their initial values via attributes.
The purpose of directly connecting a component to a provider is to allow the component to obtain both its initial value and additional configuration from the provider in the absence of a form. In this case, the provider supplies the options for possible values.
It is assumed that the value options from the provider may differ from those defined in the provider's data element. Likewise, the value entered by the user may not necessarily be used by the provider and might have a different data type or purpose. In the example described, the provider contains two data elements, each with its own value. The component retrieves these values and converts them into value options.
Given this design, the component only fetches the initial value from the provider's data. Subsequent changes to the component's value do not affect the provider’s data, and vice versa: changes in the provider's data do not influence the component’s data. Furthermore, when determining the validity of its data, the component does not rely on the provider's data settings.
If needed, this behavior can be easily modified — for example, by reinitializing the component whenever the provider’s data changes. However, such functionality is not implemented in the base component.
In the base component, it is assumed that the provider transfers the initial value to the component once and does not affect the component's operation thereafter.
Nevertheless, the base component has a side effect: it depends on the provider’s state. If the provider transitions to an error or loading state, the component will respond accordingly. While this functionality can be useful for certain tasks, it is likely unnecessary in many cases.
Attributes
id | The component's identifier |
---|---|
field_name | The name of the data element whose value the user modifies |
field_value | The initial displayed value |
checked_value | The value passed in the event when the checked state is set |
not_checked_value | The value passed in the event when the checked state is removed |
placeholder | A user prompt |
Almost all of the component's attributes are standard for input fields. These include field_name, which defines the identifier of the element the user wishes to modify, field_value, which sets the initial value, and placeholder, which defines the text hint next to the input field.
However, there are two attributes that are unique to KoiFormFieldBinary: checked_value and not_checked_value. These string values are passed in the koi-form-field-change event depending on the state set by the user.
Component State
The KoiFormFieldBinary component is a subclass of KoiBaseControl, which provides two methods for controlling visibility: show and hide.
In addition, since KoiFormFieldBinary is an input field, it offers a set of methods for managing user access. These include enable, disable, setReadonly, and removeReadonly, defined by the KoiSocketInputEnablementToggleable behavior.
Note that because the component uses checkboxes, setting or removing the readonly attribute does not affect the ability to check or uncheck the box. However, the setReadonly and removeReadonly methods are still functional, and replacing the internal component with another can produce the expected result.
Additionally, like any input field, the component can display error messages. These can reflect either data validation and completeness errors handled by the component's data object or form-related errors, which should be handled by the form acting as the controller component. However, in the basic version of KoiFormFieldBinary, error display methods are not implemented because such errors are usually related to data validation, which should be handled at the data object level.
Similarly, the component does not provide methods to manage the value, as this responsibility lies with the user. However, if direct management is needed, it can be implemented in the component's subclasses, as demonstrated with the KoiFormFieldString example.
Event
The KoiFormFieldBinary component has its own data but does not implement the KoiChangedEventDispatchable behavior and therefore does not trigger the koi-changed event. Instead, it implements the KoiFormFieldChangedEventDispatchable behavior, which allows it to trigger the koi-form-field-change event.
The koi-form-field-change event has the bubbles property set to true, meaning it propagates through the DOM tree. This allows for the creation of composite input components with multiple fields and internal data validation logic based on events.
To intercept the koi-form-field-change event, the controller component must implement the KoiFormFieldChangesInterceptable behavior. The controller can then use methods from the KoiFormFieldData object, such as getFieldName and getFieldValue. These methods allow the retrieval of the data field’s name and the value associated with the input field.
If the goal is not to retrieve the value but only to determine whether it is the primary value, the method isPrimaryOptionSelected can be used.
An interception example is shown above, where the controller component (panel) intercepts input field changes by using the _updateOwnDataWhenSocketChanged method.
Application
Input fields are typically not used alone but as part of forms. For the KoiFormFieldBinary component, the same considerations apply as for the KoiFormFieldString component.
However, it is advisable not to use KoiFormFieldBinary as a regular toggle. The purpose of an input field is to collect data from the user and pass it to the controller component through an event. For control operations, the KoiSwitch component is more appropriate, as it visually resembles KoiFormFieldBinary but is specifically designed for that functionality.