Merge branch 'feature/atomic-vds-radioButton' into 'develop'

VDS Brand 3.0 Radiobutton

### Summary
VDS Brand 3.0 Radiobutton, RadiobuttonItem for IOS
* RadiobuttonGroup will be a later integration since this is not in the app at this time.

### JIRA Ticket
https://onejira.verizon.com/browse/ONEAPP-7004

Co-authored-by: Matt Bruce <matt.bruce@verizon.com>

See merge request https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui/-/merge_requests/1153
This commit is contained in:
Pfeil, Scott Robert 2024-07-30 20:07:46 +00:00
commit fa650bafb5
8 changed files with 245 additions and 233 deletions

View File

@ -7,37 +7,35 @@
// //
import UIKit import UIKit
import VDSCoreTokens import VDS
@objcMembers open class RadioButton: Control, MFButtonProtocol { @objcMembers open class RadioButton: VDS.RadioButton, RadioButtonSelectionHelperProtocol, VDSMoleculeViewProtocol, MFButtonProtocol, MVMCoreUIViewConstrainingProtocol {
//-------------------------------------------------- //------------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //------------------------------------------------------
open var viewModel: RadioButtonModel!
public var diameter: CGFloat = 20 { open var delegateObject: MVMCoreUIDelegateObject?
didSet { widthConstraint?.constant = diameter } open var additionalData: [AnyHashable : Any]?
open var radioButtonModel: RadioButtonModel {
viewModel
} }
@objc public override var isSelected: Bool { // Form Validation
open var fieldKey: String?
open var fieldValue: JSONValue?
open var groupName: String?
open override var isSelected: Bool {
didSet { didSet {
radioModel?.state = isSelected viewModel.state = isSelected
updateAccessibilityLabel() if oldValue != isSelected {
sendActions(for: .valueChanged)
}
} }
} }
public var enabledColor: UIColor {
return radioModel?.inverted ?? false ? VDSColor.elementsPrimaryOndark : VDSColor.elementsPrimaryOnlight lazy public var radioGroupName: String? = { viewModel.fieldKey }()
}
public var disabledColor: UIColor {
return radioModel?.inverted ?? false ? VDSColor.interactiveDisabledOndark : VDSColor.interactiveDisabledOnlight
}
public var delegateObject: MVMCoreUIDelegateObject?
var additionalData: [AnyHashable: Any]?
public var radioModel: RadioButtonModel? {
model as? RadioButtonModel
}
lazy public var radioGroupName: String? = { radioModel?.fieldKey }()
lazy public var radioButtonSelectionHelper: RadioButtonSelectionHelper? = { lazy public var radioButtonSelectionHelper: RadioButtonSelectionHelper? = {
@ -48,132 +46,108 @@ import VDSCoreTokens
return radioButtonModel return radioButtonModel
}() }()
public override var isEnabled: Bool { //--------------------------------------------------
didSet { // MARK: - Initializers
isUserInteractionEnabled = isEnabled //--------------------------------------------------
setNeedsDisplay()
} override public init(frame: CGRect) {
super.init(frame: frame)
} }
//-------------------------------------------------- /// There is currently no intention on using xib files.
// MARK: - Constraints required public init?(coder aDecoder: NSCoder) {
//-------------------------------------------------- super.init(coder: aDecoder)
fatalError("xib file is not implemented for Checkbox.")
public var widthConstraint: NSLayoutConstraint?
public var heightConstraint: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
let color = isEnabled == false ? disabledColor.cgColor : enabledColor.cgColor
layer.cornerRadius = bounds.width * 0.5
layer.borderColor = color
layer.borderWidth = bounds.width * 0.0333
if isSelected {
// Space around inner circle is 1/5 the size
context.addEllipse(in: CGRect(x: bounds.width * 0.2,
y: bounds.height * 0.2,
width: bounds.width * 0.6,
height: bounds.height * 0.6))
context.setFillColor(color)
context.fillPath()
}
} }
public convenience required init() {
self.init(frame:.zero)
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Validation // MARK: - Validation
//-------------------------------------------------- //--------------------------------------------------
/// The action performed when tapped. public func isValidField() -> Bool { isSelected }
func tapAction() {
if !isEnabled { public func formFieldName() -> String? {
return viewModel.fieldKey
} }
public func formFieldGroupName() -> String? {
viewModel.fieldKey
}
public func formFieldValue() -> AnyHashable? {
guard let radioModel = viewModel, radioModel.enabled else { return nil }
return radioModel.fieldValue
}
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
public func viewModelDidUpdate() {
//events
viewModel.updateUI = {
MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in
guard let self = self else { return }
let isValid = viewModel.isValid ?? true
showError = !isValid
isEnabled = viewModel.enabled
})
}
isSelected = viewModel.state
isEnabled = viewModel.enabled && !viewModel.readOnly
RadioButtonSelectionHelper.setupForRadioButtonGroup(viewModel, self, delegateObject: delegateObject)
}
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
open override func toggle() {
guard !isSelected, isEnabled else { return }
//removed error
if showError && isSelected == false {
showError.toggle()
}
let wasPreviouslySelected = isSelected let wasPreviouslySelected = isSelected
if let radioButtonModel = radioButtonSelectionHelper { if let radioButtonSelectionHelper {
radioButtonModel.selected(self) radioButtonSelectionHelper.selected(self)
} else { } else {
isSelected = !isSelected isSelected = !isSelected
} }
if let radioModel = radioModel, let actionModel = radioModel.action, isSelected, !wasPreviouslySelected { if let actionModel = viewModel.action, isSelected, !wasPreviouslySelected {
Task(priority: .userInitiated) { Task(priority: .userInitiated) {
try await Button.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: radioModel) try await Button.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: viewModel)
} }
} }
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
setNeedsDisplay() setNeedsUpdate()
}
public func isValidField() -> Bool { isSelected }
public func formFieldName() -> String? {
radioModel?.fieldKey
}
public func formFieldGroupName() -> String? {
radioModel?.fieldKey
}
public func formFieldValue() -> AnyHashable? {
guard let radioModel = radioModel, radioModel.enabled else { return nil }
return radioModel.fieldValue
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Methods // MARK: - Actions
//-------------------------------------------------- //--------------------------------------------------
/// Adjust accessibility label based on state of RadioButton. /// This will toggle the state of the Checkbox and execute the actionBlock if provided.
func updateAccessibilityLabel() { public func tapAction() {
if let message = MVMCoreUIUtility.hardcodedString(withKey: "radio_button"), toggle()
let selectedState = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "radio_selected_state" : "radio_not_selected_state") {
accessibilityLabel = message + selectedState
}
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - MVMViewProtocol // MARK: - MoleculeViewProtocol
//-------------------------------------------------- //--------------------------------------------------
open override func setupView() { open func needsToBeConstrained() -> Bool { true }
super.setupView()
backgroundColor = .clear public func horizontalAlignment() -> UIStackView.Alignment { .leading }
clipsToBounds = true
widthConstraint = widthAnchor.constraint(equalToConstant: 20) public func updateView(_ size: CGFloat) {}
widthConstraint?.isActive = true
heightConstraint = heightAnchor.constraint(equalTo: widthAnchor, multiplier: 1)
heightConstraint?.isActive = true
addTarget(self, action: #selector(tapAction), for: .touchUpInside)
isAccessibilityElement = true
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint")
accessibilityTraits = .button
updateAccessibilityLabel()
}
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
self.delegateObject = delegateObject
self.additionalData = additionalData
guard let model = model as? RadioButtonModel else { return }
isSelected = model.state
isEnabled = model.enabled && !model.readOnly
RadioButtonSelectionHelper.setupForRadioButtonGroup(model, self, delegateObject: delegateObject)
}
public override func reset() {
super.reset()
backgroundColor = .clear
}
} }

View File

@ -7,48 +7,29 @@
// //
import MVMCore import MVMCore
import VDS
open class RadioButtonModel: FormFieldModel {
open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
public static var identifier: String = "radioButton" public static override var identifier: String { "radioButton" }
public var id: String = UUID().uuidString
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var state: Bool = false public var state: Bool = false
public var enabled: Bool = true
public var readOnly: Bool = false
/// The specific value to send to server. TODO: update this to be more generic. /// The specific value to send to server. TODO: update this to be more generic.
public var fieldValue: String? public var fieldValue: String?
public var baseValue: AnyHashable?
public var groupName: String = FormValidator.defaultGroupName
public var fieldKey: String?
public var action: ActionModelProtocol? public var action: ActionModelProtocol?
public var inverted: Bool = false
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
//-------------------------------------------------- //--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case id
case moleculeName
case backgroundColor
case accessibilityIdentifier
case state case state
case enabled
case fieldValue case fieldValue
case fieldKey
case groupName
case action case action
case readOnly
case inverted
} }
//-------------------------------------------------- //--------------------------------------------------
@ -56,69 +37,50 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
//-------------------------------------------------- //--------------------------------------------------
public init(_ state: Bool) { public init(_ state: Bool) {
super.init()
self.state = state self.state = state
baseValue = state self.baseValue = state
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Validation // MARK: - Validation
//-------------------------------------------------- //--------------------------------------------------
public func formFieldValue() -> AnyHashable? { public override func formFieldValue() -> AnyHashable? {
guard enabled else { return nil } guard enabled else { return nil }
return fieldValue return fieldValue
} }
//-------------------------------------------------- open override func setValidity(_ valid: Bool, errorMessage: String?) {
// MARK: - Server Value if let ruleErrorMessage = errorMessage, fieldKey != nil {
//-------------------------------------------------- self.errorMessage = ruleErrorMessage
open func formFieldServerValue() -> AnyHashable? { }
return formFieldValue() isValid = valid
updateUI?()
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Codec // MARK: - Codec
//-------------------------------------------------- //--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) { if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) {
self.state = state self.state = state
} }
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
baseValue = state baseValue = state
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
self.groupName = groupName
}
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
action = try typeContainer.decodeModelIfPresent(codingKey: .action) action = try typeContainer.decodeModelIfPresent(codingKey: .action)
if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) {
self.inverted = inverted
}
} }
public func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encode(id, forKey: .id)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(state, forKey: .state) try container.encode(state, forKey: .state)
try container.encode(enabled, forKey: .enabled)
try container.encode(readOnly, forKey: .readOnly)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encodeIfPresent(groupName, forKey: .groupName)
try container.encodeIfPresent(fieldValue, forKey: .fieldValue) try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
try container.encodeModelIfPresent(action, forKey: .action) try container.encodeModelIfPresent(action, forKey: .action)
try container.encodeIfPresent(inverted, forKey: .inverted)
} }
} }

View File

@ -6,6 +6,10 @@
// Copyright © 2019 Verizon Wireless. All rights reserved. // Copyright © 2019 Verizon Wireless. All rights reserved.
// //
public protocol RadioButtonSelectionHelperProtocol: AnyObject {
var isSelected: Bool { get set }
var radioButtonModel: RadioButtonModel { get }
}
@objcMembers public class RadioButtonSelectionHelper: FormFieldProtocol { @objcMembers public class RadioButtonSelectionHelper: FormFieldProtocol {
//-------------------------------------------------- //--------------------------------------------------
@ -14,7 +18,7 @@
public var fieldKey: String? public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName public var groupName: String = FormValidator.defaultGroupName
private var selectedRadioButton: RadioButton? private var selectedRadioButton: RadioButtonSelectionHelperProtocol?
private var selectedRadioButtonModel: RadioButtonModel? private var selectedRadioButtonModel: RadioButtonModel?
public var baseValue: AnyHashable? public var baseValue: AnyHashable?
public var enabled: Bool = true public var enabled: Bool = true
@ -24,7 +28,7 @@
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public func set(_ radioButtonModel: RadioButtonModel, _ radioButton: RadioButton) { public func set(_ radioButtonModel: RadioButtonModel, _ radioButton: RadioButtonSelectionHelperProtocol) {
self.fieldKey = radioButtonModel.fieldKey self.fieldKey = radioButtonModel.fieldKey
self.groupName = radioButtonModel.groupName self.groupName = radioButtonModel.groupName
@ -49,7 +53,7 @@
// MARK: - Functions // MARK: - Functions
//-------------------------------------------------- //--------------------------------------------------
public static func setupForRadioButtonGroup(_ radioButtonModel: RadioButtonModel, _ radioButton: RadioButton, delegateObject: MVMCoreUIDelegateObject?) { public static func setupForRadioButtonGroup(_ radioButtonModel: RadioButtonModel, _ radioButton: RadioButtonSelectionHelperProtocol, delegateObject: MVMCoreUIDelegateObject?) {
guard let groupName = radioButtonModel.fieldKey, guard let groupName = radioButtonModel.fieldKey,
let formValidator = delegateObject?.formHolderDelegate?.formValidator let formValidator = delegateObject?.formHolderDelegate?.formValidator
@ -61,10 +65,10 @@
FormValidator.setupValidation(for: radioButtonSelectionHelper, delegate: delegateObject?.formHolderDelegate) FormValidator.setupValidation(for: radioButtonSelectionHelper, delegate: delegateObject?.formHolderDelegate)
} }
public func selected(_ radioButton: RadioButton) { public func selected(_ radioButton: RadioButtonSelectionHelperProtocol) {
// Checks because the view could be reused // Checks because the view could be reused
if selectedRadioButton?.radioModel === selectedRadioButtonModel { if selectedRadioButton?.radioButtonModel === selectedRadioButtonModel {
selectedRadioButton?.isSelected = false selectedRadioButton?.isSelected = false
} else { } else {
selectedRadioButtonModel?.state = false selectedRadioButtonModel?.state = false
@ -72,7 +76,7 @@
selectedRadioButton = radioButton selectedRadioButton = radioButton
selectedRadioButton?.isSelected = true selectedRadioButton?.isSelected = true
selectedRadioButtonModel = selectedRadioButton?.radioModel selectedRadioButtonModel = selectedRadioButton?.radioButtonModel
} }
} }

View File

@ -81,9 +81,7 @@
func updateAccessibilityLabel() { func updateAccessibilityLabel() {
var message = "" var message = ""
radioButton.updateAccessibilityLabel()
if let radioButtonLabel = radioButton.accessibilityLabel { if let radioButtonLabel = radioButton.accessibilityLabel {
message += radioButtonLabel + ", " message += radioButtonLabel + ", "
} }

View File

@ -98,9 +98,7 @@ import UIKit
func updateAccessibilityLabel() { func updateAccessibilityLabel() {
var message = "" var message = ""
radioButton.updateAccessibilityLabel()
if let radioButtonLabel = radioButton.accessibilityLabel { if let radioButtonLabel = radioButton.accessibilityLabel {
message += radioButtonLabel + ", " message += radioButtonLabel + ", "
} }

View File

@ -85,7 +85,6 @@ open class ListLeftVariableRadioButtonBodyText: TableViewCell {
var message = "" var message = ""
radioButton.updateAccessibilityLabel()
if let radioButtonLabel = radioButton.accessibilityLabel { if let radioButtonLabel = radioButton.accessibilityLabel {
message += radioButtonLabel + ", " message += radioButtonLabel + ", "
} }

View File

@ -7,54 +7,121 @@
// //
import UIKit import UIKit
import VDS
@objcMembers public class RadioButtonLabel: VDS.RadioButtonItem, RadioButtonSelectionHelperProtocol, VDSMoleculeViewProtocol, MFButtonProtocol {
@objcMembers public class RadioButtonLabel: View { //------------------------------------------------------
// MARK: - Properties
public let radioButton = RadioButton() //------------------------------------------------------
var delegateObject: MVMCoreUIDelegateObject? open var viewModel: RadioButtonLabelModel!
let label = Label() open var delegateObject: MVMCoreUIDelegateObject?
open var additionalData: [AnyHashable : Any]?
public override func updateView(_ size: CGFloat) {
super.updateView(size)
radioButton.updateView(size)
label.updateView(size)
}
open override func setupView() { open var radioButtonModel: RadioButtonModel {
super.setupView() viewModel.radioButton
}
addSubview(radioButton) // Form Validation
radioButton.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 0).isActive = true var fieldKey: String?
radioButton.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor, constant: PaddingOne).isActive = true var fieldValue: JSONValue?
layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true var groupName: String?
radioButton.centerYAnchor.constraint(equalTo: layoutMarginsGuide.centerYAnchor).isActive = true
if let rightView = createRightView() { open override var isSelected: Bool {
addSubview(rightView) didSet {
rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: Padding.Component.gutterForApplicationWidth).isActive = true radioButtonModel.state = isSelected
rightView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: 0).isActive = true if oldValue != isSelected {
sendActions(for: .valueChanged)
var constraint = rightView.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor, constant: PaddingOne) }
constraint.priority = .defaultHigh
constraint.isActive = true
constraint = layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: rightView.bottomAnchor, constant: PaddingOne)
constraint.priority = .defaultHigh
constraint.isActive = true
layoutMarginsGuide.centerYAnchor.constraint(equalTo: rightView.centerYAnchor).isActive = true
} }
} }
func createRightView() -> Container? { lazy public var radioGroupName: String? = { viewModel.radioButton.fieldKey }()
let rightView = Container(andContain: label)
return rightView lazy public var radioButtonSelectionHelper: RadioButtonSelectionHelper? = {
guard let radioGroupName = radioGroupName,
let radioButtonModel = delegateObject?.formHolderDelegate?.formValidator?.radioButtonsModelByGroup[radioGroupName]
else { return nil }
return radioButtonModel
}()
//--------------------------------------------------
// MARK: - Life Cycle
//--------------------------------------------------
@objc open func updateView(_ size: CGFloat) {}
open override func toggle() {
guard !isSelected, isEnabled else { return }
//removed error
if showError && isSelected == false {
showError.toggle()
}
let wasPreviouslySelected = isSelected
if let radioButtonSelectionHelper {
radioButtonSelectionHelper.selected(self)
} else {
isSelected = !isSelected
}
if let actionModel = viewModel.radioButton.action, isSelected, !wasPreviouslySelected {
Task(priority: .userInitiated) {
try await Button.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: viewModel)
}
}
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
} }
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { //--------------------------------------------------
guard let radioButtonLabelModel = model as? RadioButtonLabelModel else { return } // MARK: - Atomic
//--------------------------------------------------
radioButton.set(with: radioButtonLabelModel.radioButton, delegateObject, additionalData) public func viewModelDidUpdate() {
label.set(with: radioButtonLabelModel.label, delegateObject, additionalData) surface = viewModel.surface
updateRadioButton()
//primary label
labelText = viewModel.label.text
if let attributes = viewModel.label.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData) {
labelTextAttributes = attributes
}
//secondary label
if let subTitleModel = viewModel.subTitle {
childText = subTitleModel.text
if let attributes = subTitleModel.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData) {
childTextAttributes = attributes
}
}
} }
public func updateRadioButton() {
if let fieldKey = viewModel.radioButton.fieldKey {
self.fieldKey = fieldKey
}
//properties
isEnabled = viewModel.radioButton.enabled && !viewModel.radioButton.readOnly
isSelected = viewModel.radioButton.state
//forms
RadioButtonSelectionHelper.setupForRadioButtonGroup(viewModel.radioButton, self, delegateObject: delegateObject)
//events
viewModel.radioButton.updateUI = {
MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in
guard let self = self else { return }
let isValid = viewModel.radioButton.isValid ?? true
showError = !isValid
errorText = viewModel.radioButton.errorMessage
isEnabled = viewModel.radioButton.enabled
})
}
}
} }

View File

@ -8,8 +8,9 @@
import Foundation import Foundation
import MVMCore import MVMCore
import VDS
@objcMembers public class RadioButtonLabelModel: MoleculeModelProtocol { @objcMembers public class RadioButtonLabelModel: MoleculeModelProtocol, ParentMoleculeModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -21,14 +22,23 @@ import MVMCore
public var moleculeName: String = RadioButtonLabelModel.identifier public var moleculeName: String = RadioButtonLabelModel.identifier
public var radioButton: RadioButtonModel public var radioButton: RadioButtonModel
public var label: LabelModel public var label: LabelModel
public var subTitle: LabelModel?
public var inverted: Bool? = false
public var surface: Surface { inverted ?? false ? .dark : .light }
public var children: [MoleculeModelProtocol] {
guard let subTitle else { return [radioButton, label] }
return [radioButton, label, subTitle]
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(radioButton: RadioButtonModel, label: LabelModel) { public init(radioButton: RadioButtonModel, label: LabelModel, subTitle: LabelModel?) {
self.radioButton = radioButton self.radioButton = radioButton
self.label = label self.label = label
self.subTitle = subTitle
} }
} }