public RadioBasedSingleChoice(string labelOrNull = null, RadioBasedSingleChoiceItemAdder customItemAdder = null) { BeforeAddItems = (element, i) => null; ItemAdder = customItemAdder ?? ((ctx, cntnr, rawItem, itemElem, lblElem, itemNo) => { cntnr.AppendChild(itemElem); cntnr.AppendChild(lblElem); }); _uniqueNumberAsName = UniqueIdGenerator.GenerateAsString(); _container = new HTMLDivElement(); _container.ClassName = GetType().FullNameWithoutGenerics(); if (labelOrNull != null) { _genericLabelOrNull = new HTMLLabelElement { TextContent = labelOrNull }; _container.AppendChild(_genericLabelOrNull); } _logic = new ControlWithValueLogic <Tuple <string, string> >( (newVal, isUser) => Changed?.Invoke(newVal, isUser), () => { var active = _valueToItem.Values.FirstOrDefault(x => x.Checked); return(active == null ? Tuple.Create("", "") : Tuple.Create(active.Value, _valueToLabel[active.Value])); }, v => { var emptying = v == null || string.IsNullOrEmpty(v.Item1); Logger.Debug(GetType(), "setPhysicalValue emptying?={0} value=({1};{2})", emptying, v?.Item1, v?.Item2); if (emptying) { foreach (var x in _valueToItem.Values) { if (x.Checked) { x.Checked = false; break; } } return; } _valueToItem[v.Item1].Checked = true; }, () => _valueToItem.Any() && !_valueToItem.First().Value.Disabled, v => _valueToItem.Values.ForEach(x => _valueToItem.First().Value.Disabled = !v), () => _container.ClassList.Contains(Magics.CssClassIsValidating), v => _container.AddOrRemoveClass(v, Magics.CssClassIsValidating) ); _logic.ValueToString = x => x == null ? "<Tuple null>" : $"<Tuple fst={x.Item1} snd={x.Item2}>"; }