refactored to use VDS Dropdown Select

Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
Matt Bruce 2024-07-10 14:37:04 -05:00
parent 8bf4a28b0f
commit 981bdac292
2 changed files with 91 additions and 64 deletions

View File

@ -7,19 +7,41 @@
// //
import UIKit import UIKit
import VDS
open class ItemDropdownEntryField: VDS.DropdownSelect, VDSMoleculeViewProtocol {
//------------------------------------------------------
// MARK: - Properties
//------------------------------------------------------
open var viewModel: ItemDropdownEntryFieldModel!
open var delegateObject: MVMCoreUIDelegateObject?
open var additionalData: [AnyHashable : Any]?
// Form Validation
var fieldKey: String?
var fieldValue: JSONValue?
var groupName: String?
open var pickerData: [String] = [] {
didSet {
options = pickerData.compactMap({ DropdownOptionModel(text: $0) })
}
}
open class ItemDropdownEntryField: BaseItemPickerEntryField {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
public var isValid: Bool = false
/// Closure passed here will run as picker changes items.
public var observeDropdownChange: ((String?, String) -> ())?
open var pickerData: [String] = [] /// Closure passed here will run upon dismissing the selection picker.
public var observeDropdownSelection: ((String) -> ())?
public var itemDropdownEntryFieldModel: ItemDropdownEntryFieldModel? {
model as? ItemDropdownEntryFieldModel
}
/// When selecting for first responder, allow initial selected value to appear in empty text field.
public var setInitialValueInTextField = true
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
//-------------------------------------------------- //--------------------------------------------------
@ -28,7 +50,7 @@ open class ItemDropdownEntryField: BaseItemPickerEntryField {
super.init(frame: frame) super.init(frame: frame)
} }
@objc public convenience init() { @objc public convenience required init() {
self.init(frame: .zero) self.init(frame: .zero)
} }
@ -40,14 +62,36 @@ open class ItemDropdownEntryField: BaseItemPickerEntryField {
@objc required public init?(coder: NSCoder) { @objc required public init?(coder: NSCoder) {
fatalError("ItemDropdownEntryField init(coder:) has not been implemented") fatalError("ItemDropdownEntryField init(coder:) has not been implemented")
} }
required public init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.init(model: model, delegateObject, additionalData)
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Methods // MARK: - Methods
//-------------------------------------------------- //--------------------------------------------------
open override func setup() {
super.setup()
publisher(for: .valueChanged)
.sink { [weak self] control in
guard let self, let selectedItem else { return }
viewModel.selectedIndex = control.selectId
observeDropdownSelection?(selectedItem.text)
if let valid = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) {
isValid = valid
}
}.store(in: &subscribers)
dropdownField
.publisher(for: .editingDidBegin)
.sink { [weak self] textField in
guard let self else { return }
setInitialValueFromPicker()
}.store(in: &subscribers)
dropdownField
.publisher(for: .editingDidEnd)
.sink { [weak self] textField in
guard let self else { return }
performDropdownAction()
}.store(in: &subscribers)
}
/// Sets the textField with the first value of the available picker data. /// Sets the textField with the first value of the available picker data.
@objc private func setInitialValueFromPicker() { @objc private func setInitialValueFromPicker() {
@ -55,61 +99,36 @@ open class ItemDropdownEntryField: BaseItemPickerEntryField {
guard !pickerData.isEmpty else { return } guard !pickerData.isEmpty else { return }
if setInitialValueInTextField { if setInitialValueInTextField {
let pickerIndex = pickerView.selectedRow(inComponent: 0) let pickerIndex = optionsPicker.selectedRow(inComponent: 0)
itemDropdownEntryFieldModel?.selectedIndex = pickerIndex viewModel.selectedIndex = pickerIndex
observeDropdownChange?(text, pickerData[pickerIndex]) selectId = pickerIndex
text = pickerData[pickerIndex] observeDropdownChange?(selectedItem?.text, pickerData[pickerIndex])
} }
} }
@objc override func startEditing() { public func viewModelDidUpdate() {
super.startEditing() pickerData = viewModel.options
labelText = viewModel.title
setInitialValueFromPicker() helperText = viewModel.feedback
isEnabled = viewModel.enabled
isReadOnly = viewModel.readOnly
isRequired = viewModel.required
isSelected = viewModel.selected ?? false
tooltipModel = viewModel.tooltip?.toVDSTooltipModel()
if let index = viewModel.selectedIndex {
selectId = index
optionsPicker.selectRow(index, inComponent: 0, animated: false)
pickerView(optionsPicker, didSelectRow: index, inComponent: 0)
}
FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate)
} }
@objc override func endInputing() { func performDropdownAction() {
super.endInputing() guard let actionModel = viewModel.action,
!dropdownField.isFirstResponder
guard !pickerData.isEmpty else { return } else { return }
MVMCoreUIActionHandler.performActionUnstructured(with: actionModel, sourceModel: viewModel, additionalData: additionalData, delegateObject: delegateObject)
observeDropdownSelection?(pickerData[pickerView.selectedRow(inComponent: 0)])
}
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ItemDropdownEntryFieldModel else { return }
pickerData = model.options
if let index = model.selectedIndex {
self.pickerView.selectRow(index, inComponent: 0, animated: false)
self.pickerView(pickerView, didSelectRow: index, inComponent: 0)
}
} }
//-------------------------------------------------- public func updateView(_ size: CGFloat) { }
// MARK: - Picker Delegate
//--------------------------------------------------
@objc public override func numberOfComponents(in pickerView: UIPickerView) -> Int { 1 }
@objc public override func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
pickerData.count
}
@objc public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
guard !pickerData.isEmpty else { return nil }
return pickerData[row]
}
@objc public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
guard !pickerData.isEmpty else { return }
itemDropdownEntryFieldModel?.selectedIndex = row
observeDropdownChange?(text, pickerData[row])
text = pickerData[row]
}
} }

View File

@ -5,16 +5,18 @@
// Created by Kevin Christiano on 1/22/20. // Created by Kevin Christiano on 1/22/20.
// Copyright © 2020 Verizon Wireless. All rights reserved. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
import VDS
@objcMembers open class ItemDropdownEntryFieldModel: BaseItemPickerEntryFieldModel { @objcMembers open class ItemDropdownEntryFieldModel: TextEntryFieldModel {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
public override class var identifier: String { "dropDown" } public override class var identifier: String { "dropDown" }
public var action: ActionModelProtocol?
public var options: [String] = [] public var options: [String] = []
public var selectedIndex: Int? public var selectedIndex: Int?
public var tooltip: TooltipModel?
public init(with options: [String], selectedIndex: Int? = nil) { public init(with options: [String], selectedIndex: Int? = nil) {
self.options = options self.options = options
@ -42,6 +44,8 @@
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case options case options
case selectedIndex case selectedIndex
case action
case tooltip
} }
//-------------------------------------------------- //--------------------------------------------------
@ -58,6 +62,8 @@
self.selectedIndex = selectedIndex self.selectedIndex = selectedIndex
baseValue = options.indices.contains(selectedIndex) ? options[selectedIndex] : nil baseValue = options.indices.contains(selectedIndex) ? options[selectedIndex] : nil
} }
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
tooltip = try typeContainer.decodeIfPresent(TooltipModel.self, forKey: .tooltip)
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
@ -65,5 +71,7 @@
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(options, forKey: .options) try container.encode(options, forKey: .options)
try container.encodeIfPresent(selectedIndex, forKey: .selectedIndex) try container.encodeIfPresent(selectedIndex, forKey: .selectedIndex)
try container.encodeModelIfPresent(action, forKey: .action)
try container.encodeIfPresent(tooltip, forKey: .tooltip)
} }
} }