import {InputElement} from "./InputElement"; import {UIEventSource} from "../../Logic/UIEventSource"; import {Utils} from "../../Utils"; export class RadioButton extends InputElement { IsSelected: UIEventSource = new UIEventSource(false); private readonly _selectedElementIndex: UIEventSource = new UIEventSource(null); private readonly value: UIEventSource; private readonly _elements: InputElement[] private readonly _selectFirstAsDefault: boolean; constructor(elements: InputElement[], selectFirstAsDefault = true) { super(undefined); this._elements = Utils.NoNull(elements); this._selectFirstAsDefault = selectFirstAsDefault; const self = this; this.value = UIEventSource.flatten(this._selectedElementIndex.map( (selectedIndex) => { if (selectedIndex !== undefined && selectedIndex !== null) { return elements[selectedIndex].GetValue() } } ), elements.map(e => e?.GetValue())); this.value.addCallback((t) => { self?.ShowValue(t); }) for (let i = 0; i < elements.length; i++) { // If an element is clicked, the radio button corresponding with it should be selected as well elements[i]?.onClick(() => { self._selectedElementIndex.setData(i); }); elements[i].IsSelected.addCallback(isSelected => { if (isSelected) { self._selectedElementIndex.setData(i); } }) } } IsValid(t: T): boolean { for (const inputElement of this._elements) { if (inputElement.IsValid(t)) { return true; } } return false; } GetValue(): UIEventSource { return this.value; } private IdFor(i) { return 'radio-' + this.id + '-' + i; } InnerRender(): string { let body = ""; for (let i = 0; i < this._elements.length; i++){ const el = this._elements[i]; const htmlElement = '' + '' + '
'; body += htmlElement; } return "
" + body + "
"; } public ShowValue(t: T): boolean { if (t === undefined) { return false; } if (!this.IsValid(t)) { return false; } // We check that what is selected matches the previous rendering for (let i = 0; i < this._elements.length; i++) { const e = this._elements[i]; if (e.IsValid(t)) { this._selectedElementIndex.setData(i); e.GetValue().setData(t); const radio = document.getElementById(this.IdFor(i)); // @ts-ignore radio?.checked = true; return; } } } InnerUpdate(htmlElement: HTMLElement) { const self = this; function checkButtons() { for (let i = 0; i < self._elements.length; i++) { const el = document.getElementById(self.IdFor(i)); // @ts-ignore if (el.checked) { self._selectedElementIndex.setData(i); } } } const el = document.getElementById(this.id); el.addEventListener("change", function () { checkButtons(); } ); if (this._selectedElementIndex.data !== null) { const el = document.getElementById(this.IdFor(this._selectedElementIndex.data)); if (el) { // @ts-ignore el.checked = true; checkButtons(); } } else if (this._selectFirstAsDefault) { this.ShowValue(this.value.data); if (this._selectedElementIndex.data === null || this._selectedElementIndex.data === undefined) { const el = document.getElementById(this.IdFor(0)); if (el) { // @ts-ignore el.checked = true; checkButtons(); } } } }; }