All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dominokit.domino.ui.forms.Radio Maven / Gradle / Ivy

/*
 * Copyright © 2019 Dominokit
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.dominokit.domino.ui.forms;

import static java.util.Objects.nonNull;
import static org.dominokit.domino.ui.forms.FormsStyles.*;
import static org.dominokit.domino.ui.utils.Domino.*;

import elemental2.dom.*;
import java.util.LinkedHashSet;
import java.util.Set;
import jsinterop.base.Js;
import org.dominokit.domino.ui.IsElement;
import org.dominokit.domino.ui.elements.DivElement;
import org.dominokit.domino.ui.elements.InputElement;
import org.dominokit.domino.ui.elements.LabelElement;
import org.dominokit.domino.ui.elements.SmallElement;
import org.dominokit.domino.ui.utils.*;
import org.gwtproject.editor.client.TakesValue;
import org.gwtproject.safehtml.shared.SafeHtml;

/**
 * The Radio class represents a radio button element in a Domino UI form.
 *
 * 

Radio buttons are typically used to allow users to make a single selection from a list of * options. A radio button can have a label and optional helper text. * *

Usage Example: * *

 Radio<String> radio = Radio.create("option1", "Option 1");
 * radio.setHelperText("Select option 1"); radio.addValueChangeHandler(value -> {
 * Window.alert("Selected value: " + value); }); 
* * @param The type of value associated with the radio button. * @see BaseDominoElement */ public class Radio extends BaseDominoElement> implements HasType, HasValue, T>, HasLabel>, HasHelperText>, AcceptDisable>, AcceptReadOnly>, Checkable>, TakesValue, HasChangeListeners, Boolean>, HasInputElement, HTMLInputElement> { private DivElement radioElement; private InputElement inputElement; private DivElement fieldInput; private LabelElement labelElement; private LazyChild noteElement; private RadioGroup radioGroup; private T value; private Set> changeListeners = new LinkedHashSet<>(); private boolean changeListenersPaused = false; /** * Creates a new Radio instance with the specified value and label. * * @param value The value associated with the radio button. * @param label The label text for the radio button. */ public Radio(T value, String label) { radioElement = div() .addCss(dui_form_radio) .appendChild(inputElement = input(getType()).addCss(dui_hidden_input)) .appendChild( fieldInput = div() .addCss(dui_field_input) .appendChild(labelElement = label().addCss(dui_form_radio_label))); noteElement = LazyChild.of(small().addCss(dui_form_radio_note), radioElement); setLabel(label); labelForId(inputElement.getDominoId()); withValue(value); EventListener listener = evt -> { if (isEnabled() && !isChecked()) { check(); } }; radioElement.addEventListener("click", listener); inputElement.addEventListener( "change", evt -> { DomGlobal.console.info("CHANGEEEEEEEED.!"); if (isEnabled() && !isReadOnly()) { setChecked(isChecked(), isChangeListenersPaused()); } }); inputElement.addEventListener( "checked", evt -> { if (isEnabled() && !isReadOnly()) { setChecked(isChecked(), isChangeListenersPaused()); } }); getInputElement().onKeyDown(keyEvents -> keyEvents.onEnter(listener)); init(this); } /** * Creates a new Radio instance with the specified value and a label generated from the value. * * @param value The value associated with the radio button. */ public Radio(T value) { this(value, String.valueOf(value)); } /** * Creates a new Radio instance with the specified value and label. * * @param The type of value associated with the radio button. * @param value The value associated with the radio button. * @param label The label text for the radio button. * @return A new Radio instance. */ public static Radio create(E value, String label) { return new Radio<>(value, label); } /** * Creates a new Radio instance with the specified value and a label generated from the value. * * @param The type of value associated with the radio button. * @param value The value associated with the radio button. * @return A new Radio instance. */ public static Radio create(E value) { return new Radio<>(value); } /** * Gets the type of the radio button input, which is always "radio". * * @return The type of the radio button input, which is "radio". */ @Override public String getType() { return "radio"; } /** * Links the label of the radio button to its input field by setting the "for" attribute of the * label element to the "id" of the input element if not already set. */ private void linkLabelToField() { DominoElement asDominoElement = elementOf(inputElement); if (!asDominoElement.hasAttribute("id")) { inputElement.setAttribute("id", asDominoElement.getDominoId()); } labelElement.setAttribute("for", asDominoElement.getAttribute("id")); } /** * Checks the radio button, triggering change listeners if not in a paused state. * * @return This `Radio` instance. */ @Override public Radio check() { return check(isChangeListenersPaused()); } /** * Unchecks the radio button, triggering change listeners if not in a paused state. * * @return This `Radio` instance. */ @Override public Radio uncheck() { return uncheck(isChangeListenersPaused()); } /** * Checks the radio button, optionally suppressing change listener events if `silent` is true. * * @param silent If true, change listener events will not be triggered. * @return This `Radio` instance. */ @Override public Radio check(boolean silent) { return setChecked(true, silent); } /** * Unchecks the radio button, optionally suppressing change listener events if `silent` is true. * * @param silent If true, change listener events will not be triggered. * @return This `Radio` instance. */ @Override public Radio uncheck(boolean silent) { return setChecked(false, silent); } /** * Unchecks the radio button by setting its checked state to false internally. * * @return This `Radio` instance. */ Radio uncheckSelf() { inputElement.element().checked = false; return this; } /** * Toggles the checked state of the radio button, optionally suppressing change listener events if * `silent` is true. * * @param silent If true, change listener events will not be triggered. * @return This `Radio` instance. */ @Override public Radio toggleChecked(boolean silent) { return setChecked(!isChecked(), silent); } /** * Toggles the checked state of the radio button to the specified `checkedState`, optionally * suppressing change listener events if `silent` is true. * * @param checkedState The desired checked state. * @param silent If true, change listener events will not be triggered. * @return This `Radio` instance. */ @Override public Radio toggleChecked(boolean checkedState, boolean silent) { return setChecked(checkedState, silent); } /** * Toggles the checked state of the radio button, optionally suppressing change listener events if * not in a paused state. * * @return This `Radio` instance. */ @Override public Radio toggleChecked() { return setChecked(!isChecked(), isChangeListenersPaused()); } /** * Sets the checked state of the radio button to the specified `value`, optionally suppressing * change listener events if `silent` is true. * * @param value The desired checked state. * @param silent If true, change listener events will not be triggered. * @return This `Radio` instance. */ private Radio setChecked(boolean value, boolean silent) { boolean oldState = isChecked(); if (value == oldState) { onChanged(silent); return this; } if (nonNull(radioGroup)) { if (!(radioGroup.isReadOnly() || radioGroup.isDisabled())) { T oldValue = (T) radioGroup.getValue(); radioGroup.getRadios().stream() .filter(Radio::isChecked) .findFirst() .ifPresent(radio -> radio.uncheckSelf()); inputElement.element().checked = value; if (!silent) { triggerChangeListeners(oldState, isChecked()); } radioGroup.onSelectionChanged(oldValue, this, silent); } } else { inputElement.element().checked = value; if (!silent) { triggerChangeListeners(oldState, isChecked()); } } return this; } private Radio onChanged(boolean silent) { if (nonNull(radioGroup)) { if (!(radioGroup.isReadOnly() || radioGroup.isDisabled())) { if (!silent) { triggerChangeListeners(!isChecked(), isChecked()); } radioGroup.onSelectionChanged((T) radioGroup.getValue(), this, silent); } } else { if (!silent) { triggerChangeListeners(!isChecked(), isChecked()); } } return this; } /** * Checks if the radio button is currently checked. * * @return True if the radio button is checked, false otherwise. */ @Override public boolean isChecked() { return inputElement.element().checked; } /** * Gets the DOM element representing this radio button. * * @return The DOM element of this radio button. */ @Override public HTMLDivElement element() { return radioElement.element(); } /** * Gets the name of the radio button's input element. * * @return The name of the radio button's input element. */ String getName() { return inputElement.element().name; } /** * Sets the name attribute of the radio button's input element. * * @param name The name to set. * @return This `Radio` instance. */ Radio setName(String name) { inputElement.element().name = name; return this; } /** * Sets the value of the radio button and optionally triggers change listeners. * * @param value The value to set. * @return This `Radio` instance. */ @Override public Radio withValue(T value) { return withValue(value, isChangeListenersPaused()); } /** * Sets the value of the radio button and optionally triggers change listeners. * * @param value The value to set. * @param silent If `true`, change listeners won't be triggered. * @return This `Radio` instance. */ @Override public Radio withValue(T value, boolean silent) { setValue(value); return this; } /** * Sets the value of the radio button. * * @param value The value to set. */ @Override public void setValue(T value) { this.value = value; } /** * Gets the current value of the radio button. * * @return The current value of the radio button. */ @Override public T getValue() { return this.value; } /** * Sets the label of the radio button. * * @param label The label text to set. * @return This `Radio` instance. */ @Override public Radio setLabel(String label) { labelElement.textContent(label); return this; } /** * Sets the label of the radio button with HTML content provided as SafeHtml. * * @param safeHtml The SafeHtml content to set as the label. * @return This `Radio` instance. */ public Radio setLabel(SafeHtml safeHtml) { labelElement.clearElement().setInnerHtml(safeHtml.asString()); return this; } /** * Sets the label of the radio button with a custom DOM Node element. * * @param node The DOM Node element to set as the label. * @return This `Radio` instance. */ public Radio setLabel(Node node) { elementOf(labelElement).clearElement().appendChild(node); return this; } /** * Sets the label of the radio button with an IsElement instance. * * @param element The IsElement instance whose element will be set as the label. * @return This `Radio` instance. */ public Radio setLabel(IsElement element) { return setLabel(element.element()); } /** * Gets the text content of the radio button's label. * * @return The text content of the radio button's label. */ @Override public String getLabel() { return labelElement.element().textContent; } /** * Enables the radio button for user interaction. * * @return This `Radio` instance. */ @Override public Radio enable() { radioElement.enable(); inputElement.enable(); return this; } /** * Disables the radio button, preventing user interaction. * * @return This `Radio` instance. */ @Override public Radio disable() { radioElement.disable(); inputElement.disable(); return this; } /** * Retrieves the helper text associated with this radio button. * * @return The helper text. */ @Override public String getHelperText() { return noteElement.get().getTextContent(); } /** * Sets the helper text for this radio button. * * @param text The helper text to set. * @return This `Radio` instance. */ @Override public Radio setHelperText(String text) { noteElement.get().setTextContent(text); return this; } /** * Checks if the radio button is enabled for user interaction. * * @return `true` if the radio button is enabled, `false` otherwise. */ @Override public boolean isEnabled() { return !(inputElement.isDisabled() || radioElement.isDisabled() || radioGroup.isDisabled()); } /** * Associates a radio group with this radio button. * * @param radioGroup The radio group to associate. */ void setGroup(RadioGroup radioGroup) { this.radioGroup = radioGroup; } /** * Retrieves the input element associated with this radio button. * * @return The input element. */ public DominoElement getInputElement() { return inputElement.toDominoElement(); } /** * Retrieves the string representation of the current value of this radio button. * * @return The string representation of the value. */ public String getStringValue() { return String.valueOf(getValue()); } /** * Sets focus on the radio button element if it's not disabled. * * @return This `Radio` instance. */ @Override public Radio focus() { if (!isDisabled()) { if (!isAttached()) { ElementUtil.onAttach( getInputElement(), mutationRecord -> getInputElement().element().focus()); } else { getInputElement().element().focus(); } } return this; } /** * Removes focus from the radio button element. * * @return This `Radio` instance. */ @Override public Radio unfocus() { if (!isAttached()) { ElementUtil.onAttach( getInputElement(), mutationRecord -> { getInputElement().element().blur(); }); } else { getInputElement().element().blur(); } return this; } /** * Checks if the radio button element is currently focused. * * @return `true` if the radio button is focused, `false` otherwise. */ @Override public boolean isFocused() { if (nonNull(DomGlobal.document.activeElement)) { String dominoId = elementOf(Js.uncheckedCast(DomGlobal.document.activeElement)).getDominoId(); return nonNull(radioElement.querySelector("[domino-uuid=\"" + dominoId + "\"]")); } return false; } /** * Associates the given `id` with the label element for accessibility purposes. * * @param id The `id` to associate with the label. * @return This `Radio` instance. */ @Override public Radio labelForId(String id) { DominoElement asDominoElement = elementOf(inputElement); if (!asDominoElement.hasAttribute("id")) { inputElement.setAttribute("id", asDominoElement.getDominoId()); } labelElement.setAttribute("for", asDominoElement.getAttribute("id")); return this; } /** * Pauses change listeners for this radio button. * * @return This `Radio` instance. */ @Override public Radio pauseChangeListeners() { this.changeListenersPaused = true; return this; } /** * Resumes change listeners for this radio button. * * @return This `Radio` instance. */ @Override public Radio resumeChangeListeners() { this.changeListenersPaused = false; return this; } /** * Toggles the pause state of change listeners for this radio button. * * @param toggle `true` to pause change listeners, `false` to resume. * @return This `Radio` instance. */ @Override public Radio togglePauseChangeListeners(boolean toggle) { this.changeListenersPaused = toggle; return this; } /** * Retrieves the set of change listeners associated with this radio button. * * @return The set of change listeners. */ @Override public Set> getChangeListeners() { return changeListeners; } /** * Checks if change listeners for this radio button are currently paused. * * @return `true` if change listeners are paused, `false` otherwise. */ @Override public boolean isChangeListenersPaused() { return this.changeListenersPaused; } /** * Triggers change listeners for this radio button with the given old and new values. * * @param oldValue The old value. * @param newValue The new value. * @return This `Radio` instance. */ @Override public Radio triggerChangeListeners(Boolean oldValue, Boolean newValue) { changeListeners.forEach(listener -> listener.onValueChanged(oldValue, newValue)); return this; } @Override public Radio setReadOnly(boolean readOnly) { getInputElement().setReadOnly(readOnly); return super.setReadOnly(readOnly); } /** * Retrieves the field input element associated with this radio button. * * @return The field input element. */ public DivElement getFieldInput() { return fieldInput; } /** * Retrieves the label element associated with this radio button. * * @return The label element. */ public LabelElement getLabelElement() { return labelElement; } /** * Retrieves the note element associated with this radio button. * * @return The note element. */ public SmallElement getNoteElement() { return noteElement.get(); } /** * Retrieves the radio group to which this radio button belongs. * * @return The radio group. */ public RadioGroup getRadioGroup() { return radioGroup; } /** * Allows customization of the field input element associated with this radio button using a child * handler. * * @param handler The child handler for the field input element. * @return This `Radio` instance. */ public T withFieldInput(ChildHandler, DivElement> handler) { handler.apply(this, fieldInput); return (T) this; } /** * Allows customization of the label element associated with this radio button using a child * handler. * * @param handler The child handler for the label element. * @return This `Radio` instance. */ public T withLabelElement(ChildHandler, LabelElement> handler) { handler.apply(this, labelElement); return (T) this; } /** * Allows customization of the note element associated with this radio button using a child * handler. * * @param handler The child handler for the note element. * @return This `Radio` instance. */ public T withNoteElement(ChildHandler, SmallElement> handler) { handler.apply(this, noteElement.get()); return (T) this; } /** * Allows customization of the radio group to which this radio button belongs using a child * handler. * * @param handler The child handler for the radio group. * @return This `Radio` instance. */ public T withRadioGroup(ChildHandler, RadioGroup> handler) { handler.apply(this, radioGroup); return (T) this; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy