Merge branch 'feature/optional-readonly' into 'develop'
update to Forms See merge request BPHV_MIPS/mvm_core_ui!791
This commit is contained in:
commit
e990504ce3
@ -570,6 +570,8 @@
|
||||
DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391A224421A0001AB423 /* CaretLink.swift */; };
|
||||
DBEFFA04225A829700230692 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB891E822253FA8500022516 /* Label.swift */; };
|
||||
EA41F4AC2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */; };
|
||||
EA05EFA9278DDE2C00828819 /* ClearFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA05EFA8278DDE2C00828819 /* ClearFormFieldEffectModel.swift */; };
|
||||
EA05EFAB278DE53600828819 /* ClearableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA05EFAA278DE53600828819 /* ClearableModelProtocol.swift */; };
|
||||
EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */; };
|
||||
EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; };
|
||||
EA7E67742758310500ABF773 /* EnableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */; };
|
||||
@ -577,8 +579,8 @@
|
||||
EAA0CFAF275E7D8000D65EB0 /* FormFieldEffectProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFAE275E7D8000D65EB0 /* FormFieldEffectProtocol.swift */; };
|
||||
EAA0CFB1275E823A00D65EB0 /* HideFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFB0275E823A00D65EB0 /* HideFormFieldEffectModel.swift */; };
|
||||
EAA0CFB3275E831E00D65EB0 /* DisableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFB2275E831E00D65EB0 /* DisableFormFieldEffectModel.swift */; };
|
||||
EABFC1412763BB8D00E78B40 /* StateLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC1402763BB8D00E78B40 /* StateLabel.swift */; };
|
||||
EABFC152276913E800E78B40 /* StateLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC151276913E800E78B40 /* StateLabelModel.swift */; };
|
||||
EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC1402763BB8D00E78B40 /* FormLabel.swift */; };
|
||||
EABFC152276913E800E78B40 /* FormLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC151276913E800E78B40 /* FormLabelModel.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@ -1148,6 +1150,8 @@
|
||||
DBC4391722442197001AB423 /* DashLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashLine.swift; sourceTree = "<group>"; };
|
||||
DBC4391A224421A0001AB423 /* CaretLink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretLink.swift; sourceTree = "<group>"; };
|
||||
EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRuleFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
||||
EA05EFA8278DDE2C00828819 /* ClearFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
||||
EA05EFAA278DE53600828819 /* ClearableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearableModelProtocol.swift; sourceTree = "<group>"; };
|
||||
EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButton.swift; sourceTree = "<group>"; };
|
||||
EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButtonModel.swift; sourceTree = "<group>"; };
|
||||
EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnableFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
||||
@ -1155,8 +1159,8 @@
|
||||
EAA0CFAE275E7D8000D65EB0 /* FormFieldEffectProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormFieldEffectProtocol.swift; sourceTree = "<group>"; };
|
||||
EAA0CFB0275E823A00D65EB0 /* HideFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HideFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
||||
EAA0CFB2275E831E00D65EB0 /* DisableFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
||||
EABFC1402763BB8D00E78B40 /* StateLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateLabel.swift; sourceTree = "<group>"; };
|
||||
EABFC151276913E800E78B40 /* StateLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateLabelModel.swift; sourceTree = "<group>"; };
|
||||
EABFC1402763BB8D00E78B40 /* FormLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabel.swift; sourceTree = "<group>"; };
|
||||
EABFC151276913E800E78B40 /* FormLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabelModel.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -1181,6 +1185,7 @@
|
||||
D23EA7FA2475F09800D60C34 /* CarouselItemProtocol.swift */,
|
||||
012A88C3238D86E600FE3DA1 /* CarouselItemModelProtocol.swift */,
|
||||
012A88B0238C880100FE3DA1 /* CarouselPagingModelProtocol.swift */,
|
||||
EA05EFAA278DE53600828819 /* ClearableModelProtocol.swift */,
|
||||
01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */,
|
||||
012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */,
|
||||
D28A837823C7D5BC00DFE4FC /* PageModelProtocol.swift */,
|
||||
@ -1446,8 +1451,8 @@
|
||||
94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */,
|
||||
94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */,
|
||||
DB891E822253FA8500022516 /* Label.swift */,
|
||||
EABFC151276913E800E78B40 /* StateLabelModel.swift */,
|
||||
EABFC1402763BB8D00E78B40 /* StateLabel.swift */,
|
||||
EABFC151276913E800E78B40 /* FormLabelModel.swift */,
|
||||
EABFC1402763BB8D00E78B40 /* FormLabel.swift */,
|
||||
);
|
||||
path = Label;
|
||||
sourceTree = "<group>";
|
||||
@ -2428,6 +2433,7 @@
|
||||
EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */,
|
||||
EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */,
|
||||
EAA0CFB0275E823A00D65EB0 /* HideFormFieldEffectModel.swift */,
|
||||
EA05EFA8278DDE2C00828819 /* ClearFormFieldEffectModel.swift */,
|
||||
);
|
||||
path = FormFieldEffect;
|
||||
sourceTree = "<group>";
|
||||
@ -2570,7 +2576,7 @@
|
||||
324FB6AA249366F3002552C7 /* ListLeftVariableNumberedListBodyTextModel.swift in Sources */,
|
||||
5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */,
|
||||
AA0A257824766C8A00862F64 /* ListLeftVariableIconWithRightCaretBodyTextModel.swift in Sources */,
|
||||
EABFC152276913E800E78B40 /* StateLabelModel.swift in Sources */,
|
||||
EABFC152276913E800E78B40 /* FormLabelModel.swift in Sources */,
|
||||
0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */,
|
||||
0AF60F0926B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift in Sources */,
|
||||
8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */,
|
||||
@ -2851,6 +2857,7 @@
|
||||
D29DF28321E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.m in Sources */,
|
||||
011B58F223A2AE2C0085F53C /* DropDownListItemModel.swift in Sources */,
|
||||
D2509ED12472ED9B001BFB9D /* NavigationItemModelProtocol.swift in Sources */,
|
||||
EA05EFAB278DE53600828819 /* ClearableModelProtocol.swift in Sources */,
|
||||
8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */,
|
||||
BBC0C4FD24811DBC0087C44F /* Tag.swift in Sources */,
|
||||
94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */,
|
||||
@ -2995,7 +3002,7 @@
|
||||
013F801923FB4A8E00AD8013 /* UIContentMode+Extension.swift in Sources */,
|
||||
AA104AC724472DB0004D2810 /* HeadersH1Button.swift in Sources */,
|
||||
525239C22407BD1000454969 /* ListTwoColumnPriceDetails.swift in Sources */,
|
||||
EABFC1412763BB8D00E78B40 /* StateLabel.swift in Sources */,
|
||||
EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */,
|
||||
AA997252247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift in Sources */,
|
||||
D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */,
|
||||
D23EA7FB2475F09800D60C34 /* CarouselItemProtocol.swift in Sources */,
|
||||
@ -3017,6 +3024,7 @@
|
||||
52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */,
|
||||
D2ED2812254B0EB800A1C293 /* MVMCoreTopAlertObject.m in Sources */,
|
||||
0AA4D2E125CAEC72008DB32D /* AccessibilityModelProtocol.swift in Sources */,
|
||||
EA05EFA9278DDE2C00828819 /* ClearFormFieldEffectModel.swift in Sources */,
|
||||
C003506123AA94CD00B6AC29 /* Button.swift in Sources */,
|
||||
DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */,
|
||||
D29C559025C095210082E7D6 /* Video.swift in Sources */,
|
||||
|
||||
@ -44,7 +44,7 @@ import UIKit
|
||||
super.isEnabled = enabled
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -17,8 +17,8 @@ import UIKit
|
||||
//--------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//--------------------------------------------------
|
||||
public private(set) var titleLabel: StateLabel = {
|
||||
let label = StateLabel()
|
||||
public private(set) var titleLabel: FormLabel = {
|
||||
let label = FormLabel()
|
||||
label.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
return label
|
||||
}()
|
||||
@ -26,12 +26,33 @@ import UIKit
|
||||
public private(set) var entryFieldContainer = EntryFieldContainer()
|
||||
|
||||
/// Provides contextual information on the TextField.
|
||||
public private(set) var feedbackLabel: StateLabel = {
|
||||
let label = StateLabel()
|
||||
public private(set) var feedbackLabel: FormLabel = {
|
||||
let label = FormLabel()
|
||||
label.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
return label
|
||||
}()
|
||||
|
||||
|
||||
public private(set) var errorLabel: Label = {
|
||||
let label = Label()
|
||||
label.setFontStyle(.RegularMicro)
|
||||
label.textColor = .mvmBlack
|
||||
label.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
return label
|
||||
}()
|
||||
|
||||
public lazy var stack: UIStackView = {
|
||||
errorLabel.isHidden = true
|
||||
let stack = UIStackView(arrangedSubviews: [titleLabel, entryFieldContainer, errorLabel, feedbackLabel])
|
||||
stack.axis = .vertical
|
||||
stack.alignment = .fill
|
||||
stack.distribution = .fill
|
||||
stack.setCustomSpacing(Padding.One, after: titleLabel)
|
||||
stack.setCustomSpacing(Padding.Two, after: entryFieldContainer)
|
||||
stack.setCustomSpacing(Padding.One, after: errorLabel)
|
||||
stack.translatesAutoresizingMaskIntoConstraints = false
|
||||
return stack
|
||||
}()
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Delegate
|
||||
//--------------------------------------------------
|
||||
@ -59,21 +80,26 @@ import UIKit
|
||||
feedbackLabel.isEnabled = enabled
|
||||
entryFieldContainer.isEnabled = enabled
|
||||
entryFieldModel?.enabled = enabled
|
||||
if !enabled {
|
||||
self.text = defaultText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Toggles enabled (original) or disabled UI.
|
||||
public var isRequired: Bool = true {
|
||||
didSet{
|
||||
titleLabel.isRequired = isRequired
|
||||
}
|
||||
}
|
||||
|
||||
/// Toggles error or original UI.
|
||||
public var showError: Bool {
|
||||
get { entryFieldContainer.showError }
|
||||
set (error) {
|
||||
if error {
|
||||
feedbackLabel.showError(message: self.errorMessage ?? "")
|
||||
errorLabel.text = self.errorMessage ?? ""
|
||||
errorLabel.isHidden = false
|
||||
} else {
|
||||
feedbackLabel.reset()
|
||||
errorLabel.isHidden = true
|
||||
}
|
||||
entryFieldContainer.showError = error
|
||||
entryFieldModel?.showError = error
|
||||
@ -130,25 +156,6 @@ import UIKit
|
||||
model as? EntryFieldModel
|
||||
}
|
||||
|
||||
///This is the value of the entryFieldModel.text on set
|
||||
///This is used to update the text value on a reset or when enabled is set to false
|
||||
private var defaultText: String = ""
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
//--------------------------------------------------
|
||||
|
||||
public var entryFieldContainerLeading: NSLayoutConstraint?
|
||||
public var entryFieldContainerTrailing: NSLayoutConstraint?
|
||||
|
||||
public var feedbackLabelTrailing: NSLayoutConstraint?
|
||||
public var feedbackLabelLeading: NSLayoutConstraint?
|
||||
|
||||
public var titleLabelLeading: NSLayoutConstraint?
|
||||
public var titleLabelTrailing: NSLayoutConstraint?
|
||||
|
||||
public var titleContainerDistance: NSLayoutConstraint?
|
||||
public var feedbackContainerDistance: NSLayoutConstraint?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
@ -188,37 +195,18 @@ import UIKit
|
||||
|
||||
isAccessibilityElement = false
|
||||
setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
accessibilityElements = [titleLabel, feedbackLabel]
|
||||
accessibilityElements = [titleLabel, errorLabel, feedbackLabel]
|
||||
backgroundColor = .mvmWhite
|
||||
|
||||
addSubview(titleLabel)
|
||||
|
||||
titleLabel.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true
|
||||
titleLabelLeading = titleLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
|
||||
titleLabelLeading?.isActive = true
|
||||
titleLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: titleLabel.trailingAnchor)
|
||||
titleLabelLeading?.isActive = true
|
||||
|
||||
addSubview(entryFieldContainer)
|
||||
|
||||
addSubview(stack)
|
||||
|
||||
entryFieldContainer.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
setupFieldContainerContent(entryFieldContainer)
|
||||
|
||||
titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: Padding.One)
|
||||
titleContainerDistance?.isActive = true
|
||||
entryFieldContainerLeading = entryFieldContainer.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
|
||||
entryFieldContainerLeading?.isActive = true
|
||||
entryFieldContainerTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: entryFieldContainer.trailingAnchor)
|
||||
entryFieldContainerTrailing?.isActive = true
|
||||
|
||||
addSubview(feedbackLabel)
|
||||
|
||||
feedbackContainerDistance = feedbackLabel.topAnchor.constraint(equalTo: entryFieldContainer.bottomAnchor, constant: Padding.Two)
|
||||
feedbackContainerDistance?.isActive = true
|
||||
feedbackLabelLeading = feedbackLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
|
||||
feedbackLabelLeading?.isActive = true
|
||||
feedbackLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: feedbackLabel.trailingAnchor)
|
||||
feedbackLabelTrailing?.isActive = true
|
||||
layoutMarginsGuide.bottomAnchor.constraint(equalTo: feedbackLabel.bottomAnchor).isActive = true
|
||||
|
||||
stack.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true
|
||||
stack.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true
|
||||
layoutMarginsGuide.trailingAnchor.constraint(equalTo: stack.trailingAnchor).isActive = true
|
||||
layoutMarginsGuide.bottomAnchor.constraint(equalTo: stack.bottomAnchor).isActive = true
|
||||
}
|
||||
|
||||
@objc open override func layoutSubviews() {
|
||||
@ -234,10 +222,7 @@ import UIKit
|
||||
|
||||
@objc open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
|
||||
titleLabel.updateView(size)
|
||||
feedbackLabel.updateView(size)
|
||||
entryFieldContainer.updateView(size)
|
||||
stack.updateView(size)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -295,6 +280,9 @@ import UIKit
|
||||
titleLabel.textColor = .mvmBlack
|
||||
feedbackLabel.font = Styler.Font.RegularMicro.getFont()
|
||||
feedbackLabel.textColor = .mvmBlack
|
||||
errorLabel.font = Styler.Font.RegularMicro.getFont()
|
||||
errorLabel.textColor = .mvmBlack
|
||||
errorLabel.text = nil
|
||||
entryFieldContainer.disableAllBorders = false
|
||||
feedbackLabel.text = nil
|
||||
entryFieldContainer.reset()
|
||||
@ -313,8 +301,8 @@ import UIKit
|
||||
titleLabel.setup(model: model.titleStateLabel, delegateObject, additionalData)
|
||||
feedbackLabel.setup(model: model.feedbackStateLabel, delegateObject, additionalData)
|
||||
|
||||
defaultText = model.text ?? ""
|
||||
isEnabled = model.enabled
|
||||
isEnabled = model.enabled && !model.readOnly
|
||||
isRequired = model.required
|
||||
model.updateUI = { [weak self] in
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||
guard let self = self else { return }
|
||||
@ -326,6 +314,7 @@ import UIKit
|
||||
self.showError = false
|
||||
}
|
||||
self.isEnabled = model.enabled
|
||||
self.text = model.text
|
||||
})
|
||||
}
|
||||
|
||||
@ -376,8 +365,8 @@ extension EntryField {
|
||||
}
|
||||
|
||||
extension LabelModel {
|
||||
public convenience init(fontStyle: Styler.Font, textColor: Color) {
|
||||
self.init(text: "")
|
||||
public convenience init(text: String = "", fontStyle: Styler.Font, textColor: Color) {
|
||||
self.init(text: text)
|
||||
self.fontStyle = fontStyle
|
||||
self.textColor = textColor
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
@objcMembers open class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, UIUpdatableModelProtocol {
|
||||
@objcMembers open class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, UIUpdatableModelProtocol, ClearableModelProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
@ -29,6 +29,8 @@ import Foundation
|
||||
public var errorMessage: String?
|
||||
public var errorTextColor: Color?
|
||||
public var enabled: Bool = true
|
||||
public var required: Bool = true
|
||||
public var readOnly: Bool = false
|
||||
public var showError: Bool?
|
||||
public var hideBorders = false
|
||||
public var locked: Bool?
|
||||
@ -38,20 +40,12 @@ import Foundation
|
||||
public var groupName: String = FormValidator.defaultGroupName
|
||||
public var baseValue: AnyHashable?
|
||||
public var wasInitiallySelected: Bool = false
|
||||
|
||||
//text only
|
||||
//Used for re-encoding what was decoded
|
||||
private var title: String?
|
||||
private var feedback: String?
|
||||
|
||||
//label models
|
||||
//Used for re-encoding what was decoded
|
||||
private var titleLabel: LabelModel?
|
||||
private var feedbackLabel: LabelModel?
|
||||
public var title: String?
|
||||
public var feedback: String?
|
||||
|
||||
//used to drive the EntryFieldView UI
|
||||
public var titleStateLabel: StateLabelModel
|
||||
public var feedbackStateLabel: StateLabelModel
|
||||
public var titleStateLabel: FormLabelModel
|
||||
public var feedbackStateLabel: FormLabelModel
|
||||
|
||||
public var isValid: Bool? = true {
|
||||
didSet { updateUI?() }
|
||||
@ -73,6 +67,7 @@ import Foundation
|
||||
case accessibilityIdentifier
|
||||
case title
|
||||
case enabled
|
||||
case readOnly
|
||||
case feedback
|
||||
case errorMessage
|
||||
case errorTextColor
|
||||
@ -83,8 +78,7 @@ import Foundation
|
||||
case text
|
||||
case fieldKey
|
||||
case groupName
|
||||
case titleLabel
|
||||
case feedbackLabel
|
||||
case required
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -117,8 +111,15 @@ import Foundation
|
||||
public init(with text: String) {
|
||||
self.text = text
|
||||
baseValue = text
|
||||
self.titleStateLabel = StateLabelModel(text: "")
|
||||
self.feedbackStateLabel = StateLabelModel(text: "")
|
||||
self.titleStateLabel = FormLabelModel(text: "")
|
||||
self.feedbackStateLabel = FormLabelModel(text: "")
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
public func clear() {
|
||||
self.text = ""
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -134,30 +135,21 @@ import Foundation
|
||||
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage)
|
||||
errorTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .errorTextColor)
|
||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
||||
required = try typeContainer.decodeIfPresent(Bool.self, forKey: .required) ?? true
|
||||
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
||||
locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked)
|
||||
selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected)
|
||||
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
|
||||
hideBorders = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideBorders) ?? false
|
||||
baseValue = text
|
||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||
titleLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .titleLabel)
|
||||
feedbackLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .feedbackLabel)
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
self.groupName = groupName
|
||||
}
|
||||
|
||||
//Setup the stateLabelModels
|
||||
if let titleLabel = titleLabel {
|
||||
self.titleStateLabel = StateLabelModel(model: titleLabel)
|
||||
} else {
|
||||
self.titleStateLabel = StateLabelModel(text: title ?? "")
|
||||
}
|
||||
|
||||
if let feedBackLabel = feedbackLabel {
|
||||
self.feedbackStateLabel = StateLabelModel(model: feedBackLabel)
|
||||
} else { //feedback is the model for the error
|
||||
self.feedbackStateLabel = StateLabelModel(text: feedback ?? "")
|
||||
}
|
||||
self.titleStateLabel = FormLabelModel(text: title ?? "")
|
||||
self.feedbackStateLabel = FormLabelModel(model: LabelModel(text: feedback ?? "",
|
||||
fontStyle: FormLabelModel.defaultFontStyle,
|
||||
textColor: Color(uiColor: .mvmCoolGray6)))
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
@ -166,9 +158,7 @@ import Foundation
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
||||
try container.encodeIfPresent(title, forKey: .title)
|
||||
try container.encodeIfPresent(titleLabel, forKey: .titleLabel)
|
||||
try container.encodeIfPresent(feedback, forKey: .feedback)
|
||||
try container.encodeIfPresent(feedbackLabel, forKey: .feedbackLabel)
|
||||
try container.encodeIfPresent(text, forKey: .text)
|
||||
try container.encodeIfPresent(locked, forKey: .locked)
|
||||
try container.encodeIfPresent(showError, forKey: .showError)
|
||||
@ -178,7 +168,9 @@ import Foundation
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||
|
||||
try container.encode(readOnly, forKey: .readOnly)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(required, forKey: .required)
|
||||
try container.encode(hideBorders, forKey: .hideBorders)
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele
|
||||
if self.textView.isShowingPlaceholder {
|
||||
self.textView.textColor = self.textView.placeholderTextColor
|
||||
} else {
|
||||
self.textView.textColor = (enabled ? self.textViewEntryFieldModel?.enabledTextColor : self.textViewEntryFieldModel?.disabledTextColor)?.uiColor
|
||||
self.textView.textColor = (self.textView.isEnabled ? self.textViewEntryFieldModel?.enabledTextColor : self.textViewEntryFieldModel?.disabledTextColor)?.uiColor
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -282,8 +282,5 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele
|
||||
adjustMarginConstraints(constant: 0)
|
||||
}
|
||||
|
||||
if !model.enabled {
|
||||
isEnabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,7 +95,7 @@ import MVMCore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var disabledBackgroundColor: UIColor = .clear
|
||||
public var disabledBorderColor: UIColor = .mvmCoolGray3
|
||||
public var disabledCheckColor: UIColor = .mvmCoolGray3
|
||||
@ -430,7 +430,7 @@ import MVMCore
|
||||
})
|
||||
}
|
||||
|
||||
isEnabled = model.enabled
|
||||
isEnabled = model.enabled && !model.readOnly
|
||||
|
||||
if (model.action != nil || model.offAction != nil) {
|
||||
actionBlock = { [weak self] in
|
||||
|
||||
@ -23,7 +23,8 @@
|
||||
public var backgroundColor: Color?
|
||||
public var accessibilityIdentifier: String?
|
||||
public var selected: Bool = false
|
||||
public var enabled: Bool = true
|
||||
public var enabled: Bool = true
|
||||
public var readOnly: Bool = false
|
||||
public var animated: Bool = true
|
||||
public var inverted: Bool = false
|
||||
public var round: Bool = false
|
||||
@ -54,6 +55,7 @@
|
||||
case accessibilityIdentifier
|
||||
case checked
|
||||
case enabled
|
||||
case readOnly
|
||||
case inverted
|
||||
case animated
|
||||
case round
|
||||
@ -158,10 +160,8 @@
|
||||
self.inverted = inverted
|
||||
}
|
||||
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
|
||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
||||
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
||||
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||
|
||||
@ -191,7 +191,8 @@
|
||||
try container.encodeIfPresent(disabledCheckColor, forKey: .disabledCheckColor)
|
||||
try container.encodeIfPresent(animated, forKey: .animated)
|
||||
try container.encodeIfPresent(round, forKey: .round)
|
||||
try container.encodeIfPresent(enabled, forKey: .enabled)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(readOnly, forKey: .readOnly)
|
||||
try container.encodeModelIfPresent(action, forKey: .action)
|
||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||
try container.encodeModelIfPresent(offAction, forKey: .offAction)
|
||||
|
||||
@ -62,7 +62,7 @@ import UIKit
|
||||
heartPath.close()
|
||||
heart.path = heartPath.cgPath
|
||||
heart.fillColor = isSelected ? heartModel?.activeColor.cgColor : heartModel?.inActiveColor.cgColor
|
||||
heart.opacity = 1.0
|
||||
heart.opacity = isEnabled ? 1.0 : 0.5
|
||||
heart.lineWidth = 1
|
||||
heart.strokeColor = isSelected ? UIColor.clear.cgColor : UIColor.mvmBlack.cgColor
|
||||
return heart
|
||||
@ -88,7 +88,7 @@ import UIKit
|
||||
self.additionalData = additionalData
|
||||
guard let model = model as? HeartModel else { return }
|
||||
isSelected = model.isActive
|
||||
isEnabled = model.enabled
|
||||
isEnabled = model.enabled && !model.readOnly
|
||||
updateAccessibilityLabel()
|
||||
}
|
||||
|
||||
|
||||
@ -21,8 +21,8 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
|
||||
public var inActiveColor: Color = Color(uiColor: .clear)
|
||||
public var action: ActionModelProtocol = ActionNoopModel()
|
||||
public var enabled: Bool = true
|
||||
|
||||
//--------------------------------------------------
|
||||
public var readOnly: Bool = false
|
||||
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -35,6 +35,7 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
|
||||
case inActiveColor
|
||||
case action
|
||||
case enabled
|
||||
case readOnly
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -61,9 +62,8 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
|
||||
if let action: ActionModelProtocol = try typeContainer.decodeModelIfPresent(codingKey: .action) {
|
||||
self.action = action
|
||||
}
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
||||
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
@ -76,5 +76,6 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
|
||||
try container.encode(inActiveColor, forKey: .inActiveColor)
|
||||
try container.encodeModel(action, forKey: .action)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(readOnly, forKey: .readOnly)
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ open class RadioBox: Control, MFButtonProtocol {
|
||||
public override var isEnabled: Bool {
|
||||
didSet { updateAccessibility() }
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MVMCoreViewProtocol
|
||||
//--------------------------------------------------
|
||||
@ -89,7 +89,7 @@ open class RadioBox: Control, MFButtonProtocol {
|
||||
accentColor = color
|
||||
}
|
||||
isSelected = model.selected
|
||||
isEnabled = model.enabled
|
||||
isEnabled = model.enabled && !model.readOnly
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
public var selectedAccentColor: Color?
|
||||
public var selected: Bool = false
|
||||
public var enabled: Bool = true
|
||||
public var readOnly: Bool = false
|
||||
public var strikethrough: Bool = false
|
||||
public var fieldValue: String?
|
||||
public var action: ActionModelProtocol?
|
||||
@ -39,6 +40,7 @@
|
||||
case strikethrough
|
||||
case fieldValue
|
||||
case action
|
||||
case readOnly
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -57,9 +59,8 @@
|
||||
selected = isSelected
|
||||
}
|
||||
|
||||
if let isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
enabled = isEnabled
|
||||
}
|
||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
||||
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
||||
|
||||
if let isStrikeTrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) {
|
||||
strikethrough = isStrikeTrough
|
||||
@ -79,6 +80,7 @@
|
||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
||||
try container.encode(selected, forKey: .selected)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(readOnly, forKey: .readOnly)
|
||||
try container.encode(strikethrough, forKey: .strikethrough)
|
||||
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
|
||||
try container.encodeModelIfPresent(action, forKey: .action)
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
public var groupName: String = FormValidator.defaultGroupName
|
||||
public var baseValue: AnyHashable?
|
||||
public var enabled: Bool = true
|
||||
|
||||
public var readOnly: Bool = false
|
||||
//--------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
@ -42,6 +42,7 @@
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case enabled
|
||||
case readOnly
|
||||
case selectedAccentColor
|
||||
case backgroundColor
|
||||
case accessibilityIdentifier
|
||||
@ -66,9 +67,8 @@
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
self.groupName = groupName
|
||||
}
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
||||
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
||||
baseValue = formFieldValue()
|
||||
}
|
||||
|
||||
@ -81,5 +81,7 @@
|
||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encode(groupName, forKey: .groupName)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(readOnly, forKey: .readOnly)
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ import UIKit
|
||||
open override func draw(_ rect: CGRect) {
|
||||
guard let context = UIGraphicsGetCurrentContext() else { return }
|
||||
|
||||
let color = isEnabled ? enabledColor.cgColor : disabledColor.cgColor
|
||||
let color = isEnabled == false ? disabledColor.cgColor : enabledColor.cgColor
|
||||
layer.cornerRadius = bounds.width * 0.5
|
||||
layer.borderColor = color
|
||||
layer.borderWidth = bounds.width * 0.0333
|
||||
@ -163,7 +163,7 @@ import UIKit
|
||||
guard let model = model as? RadioButtonModel else { return }
|
||||
|
||||
isSelected = model.state
|
||||
isEnabled = model.enabled
|
||||
isEnabled = model.enabled && !model.readOnly
|
||||
RadioButtonSelectionHelper.setupForRadioButtonGroup(model, self, delegateObject: delegateObject)
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
public var accessibilityIdentifier: String?
|
||||
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.
|
||||
public var fieldValue: String?
|
||||
@ -42,6 +43,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
case fieldKey
|
||||
case groupName
|
||||
case action
|
||||
case readOnly
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -72,11 +74,9 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) {
|
||||
self.state = state
|
||||
}
|
||||
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
|
||||
@ -96,6 +96,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
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)
|
||||
|
||||
@ -18,7 +18,8 @@
|
||||
private var selectedRadioButtonModel: RadioButtonModel?
|
||||
public var baseValue: AnyHashable?
|
||||
public var enabled: Bool = true
|
||||
|
||||
public var readOnly: Bool = false
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
@ -41,6 +42,7 @@
|
||||
radioButton.isSelected = false
|
||||
}
|
||||
self.enabled = radioButtonModel.enabled
|
||||
self.readOnly = radioButtonModel.readOnly
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -38,7 +38,7 @@ open class RadioSwatch: Control, MFButtonProtocol {
|
||||
updateAccessibility()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Lifecycle
|
||||
//--------------------------------------------------
|
||||
@ -64,7 +64,7 @@ open class RadioSwatch: Control, MFButtonProtocol {
|
||||
self.additionalData = additionalData
|
||||
bottomText.text = model.text
|
||||
isSelected = model.selected
|
||||
isEnabled = model.enabled
|
||||
isEnabled = model.enabled && !model.readOnly
|
||||
}
|
||||
|
||||
public override func reset() {
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
public var text: String?
|
||||
public var selected: Bool = false
|
||||
public var enabled: Bool = true
|
||||
public var readOnly: Bool = false
|
||||
public var strikethrough: Bool = false
|
||||
public var fieldValue: String?
|
||||
public var action: ActionModelProtocol?
|
||||
@ -38,6 +39,7 @@
|
||||
case strikethrough
|
||||
case fieldValue
|
||||
case action
|
||||
case readOnly
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -58,17 +60,15 @@
|
||||
if let selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) {
|
||||
self.selected = selected
|
||||
}
|
||||
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
|
||||
|
||||
if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) {
|
||||
self.strikethrough = strikethrough
|
||||
}
|
||||
|
||||
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
|
||||
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
||||
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
@ -83,5 +83,6 @@
|
||||
try container.encode(strikethrough, forKey: .strikethrough)
|
||||
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
|
||||
try container.encodeModelIfPresent(action, forKey: .action)
|
||||
try container.encode(readOnly, forKey: .readOnly)
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,7 +20,8 @@
|
||||
public var groupName: String = FormValidator.defaultGroupName
|
||||
public var baseValue: AnyHashable?
|
||||
public var enabled: Bool = true
|
||||
|
||||
public var readOnly: Bool = false
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
@ -46,6 +47,7 @@
|
||||
case fieldKey
|
||||
case groupName
|
||||
case enabled
|
||||
case readOnly
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -61,9 +63,8 @@
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
self.groupName = groupName
|
||||
}
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
||||
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
||||
baseValue = formFieldValue()
|
||||
}
|
||||
|
||||
@ -75,5 +76,7 @@
|
||||
try container.encode(swatches, forKey: .swatches)
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encode(groupName, forKey: .groupName)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(readOnly, forKey: .readOnly)
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: isEnabled ? "AccToggleHint" : "AccDisabled")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Simple means to prevent user interaction with the toggle.
|
||||
public var isLocked: Bool = false {
|
||||
didSet { isUserInteractionEnabled = !isLocked }
|
||||
@ -384,7 +384,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
isOn = model.selected
|
||||
changeStateNoAnimation(isOn)
|
||||
isAnimated = model.animated
|
||||
isEnabled = model.enabled
|
||||
isEnabled = model.enabled && !model.readOnly
|
||||
|
||||
if let accessibileString = model.accessibilityText {
|
||||
accessibilityLabel = accessibileString
|
||||
|
||||
@ -18,6 +18,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
public var selected: Bool = false
|
||||
public var animated: Bool = true
|
||||
public var enabled: Bool = true
|
||||
public var readOnly: Bool = false
|
||||
public var action: ActionModelProtocol?
|
||||
public var alternateAction: ActionModelProtocol?
|
||||
public var accessibilityText: String?
|
||||
@ -39,6 +40,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
case state
|
||||
case animated
|
||||
case enabled
|
||||
case readOnly
|
||||
case action
|
||||
case backgroundColor
|
||||
case accessibilityIdentifier
|
||||
@ -81,10 +83,6 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
self.selected = state
|
||||
}
|
||||
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
|
||||
if let animated = try typeContainer.decodeIfPresent(Bool.self, forKey: .animated) {
|
||||
self.animated = animated
|
||||
}
|
||||
@ -117,6 +115,8 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
self.groupName = groupName
|
||||
}
|
||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
||||
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
@ -136,5 +136,6 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||
try container.encode(readOnly, forKey: .readOnly)
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ open class BarsIndicatorView: CarouselIndicator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Colors the currently selected index, unique from other indicators
|
||||
public var currentIndicatorColor: UIColor {
|
||||
get { barsCarouselIndicatorModel?.currentIndicatorColor.uiColor ?? indicatorColor }
|
||||
|
||||
@ -44,7 +44,7 @@ open class NumericIndicatorView: CarouselIndicator {
|
||||
open override var isEnabled: Bool {
|
||||
didSet { setViewColor(isEnabled ? indicatorColor : disabledIndicatorColor) }
|
||||
}
|
||||
|
||||
|
||||
/// Sets the color for pageCount text, left arrow and right arrow.
|
||||
public override var indicatorColor: UIColor {
|
||||
get { super.indicatorColor }
|
||||
|
||||
@ -9,35 +9,31 @@
|
||||
import Foundation
|
||||
|
||||
/// Subclass of label that helps with different states
|
||||
public class StateLabel: Label {
|
||||
public class FormLabel: Label {
|
||||
//properties used in setting label
|
||||
private var delegateObject: MVMCoreUIDelegateObject?
|
||||
private var additionalData: [AnyHashable: Any]?
|
||||
|
||||
//models that drive the label UI
|
||||
private var stateModel: StateLabelModel!
|
||||
private var formModel: FormLabelModel!
|
||||
|
||||
//public properties
|
||||
public override var isEnabled: Bool {
|
||||
didSet{
|
||||
self.state = isEnabled ? .enabled : .disabled
|
||||
self.formModel.enabled = isEnabled
|
||||
self.set(with: isRequired ? formModel.model : formModel.requiredModel, delegateObject, additionalData)
|
||||
}
|
||||
}
|
||||
|
||||
public var isRequired: Bool = true {
|
||||
didSet{
|
||||
self.set(with: isRequired ? formModel.model : formModel.requiredModel, delegateObject, additionalData)
|
||||
}
|
||||
}
|
||||
|
||||
public override func reset(){
|
||||
super.reset()
|
||||
self.state = .enabled
|
||||
}
|
||||
|
||||
//current mode of label
|
||||
public var state: StateLabelModel.State {
|
||||
get {
|
||||
return self.stateModel.state
|
||||
}
|
||||
set {
|
||||
self.stateModel.state = newValue
|
||||
self.set(with: stateModel.model, delegateObject, additionalData)
|
||||
}
|
||||
self.isEnabled = true
|
||||
}
|
||||
|
||||
/// Used in setting up the Label for use
|
||||
@ -46,25 +42,18 @@ public class StateLabel: Label {
|
||||
/// - model: Model takes priority over a text value. The model has its own text value that will be looked at to draw the screen, this model is used for both enabled/disabled models
|
||||
/// - delegateObject: passed in from the creator
|
||||
/// - additionalData: passed in from the creator
|
||||
public func setup(model: StateLabelModel, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?){
|
||||
public func setup(model: FormLabelModel, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?){
|
||||
self.additionalData = additionalData
|
||||
self.delegateObject = delegateObject
|
||||
self.stateModel = model
|
||||
self.formModel = model
|
||||
|
||||
//default to enabled state
|
||||
self.reset()
|
||||
}
|
||||
|
||||
/// Use this to switch the label into a error state
|
||||
/// - Parameter message: message to show in the errorModel
|
||||
public func showError(message: String){
|
||||
self.stateModel.set(text: message, for: .error)
|
||||
self.state = .error
|
||||
}
|
||||
|
||||
/// Text change that will update both enabledModel and disabledModel text values
|
||||
/// - Parameter text: text you want to see
|
||||
public func set(text: String?){
|
||||
self.stateModel.set(text: text ?? "", for: .enabled)
|
||||
self.formModel.set(text: text ?? "")
|
||||
}
|
||||
}
|
||||
@ -8,37 +8,23 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public class StateLabelModel {
|
||||
public class FormLabelModel: EnableableModelProtocol {
|
||||
static let defaultFontStyle = Styler.Font.RegularMicro
|
||||
static let defaultEnabledTextColor = Color(uiColor: .mvmBlack)
|
||||
static let defaultDisabledTextColor = Color(uiColor: .mvmCoolGray3)
|
||||
static let defaultErrorTextColor = Color(uiColor: .mvmBlack)
|
||||
static let defaultRequiredTextColor = Color(uiColor: .mvmCoolGray6)
|
||||
|
||||
private var enabledModel: LabelModel
|
||||
private var disabledModel = LabelModel(fontStyle: StateLabelModel.defaultFontStyle, textColor: StateLabelModel.defaultDisabledTextColor)
|
||||
private var errorLabelModel = LabelModel(fontStyle: StateLabelModel.defaultFontStyle, textColor: StateLabelModel.defaultErrorTextColor)
|
||||
private var disabledModel = LabelModel(fontStyle: FormLabelModel.defaultFontStyle, textColor: FormLabelModel.defaultDisabledTextColor)
|
||||
|
||||
public enum State {
|
||||
case enabled
|
||||
case disabled
|
||||
case error
|
||||
}
|
||||
|
||||
//current state
|
||||
public var state: State = .enabled
|
||||
public var enabled: Bool = true
|
||||
|
||||
//model is based on current state
|
||||
public var model: LabelModel {
|
||||
switch state {
|
||||
case .enabled:
|
||||
return enabledModel
|
||||
case .disabled:
|
||||
return disabledModel
|
||||
case .error:
|
||||
return errorLabelModel
|
||||
}
|
||||
return enabled ? enabledModel: disabledModel
|
||||
}
|
||||
|
||||
|
||||
//init
|
||||
public init(model: LabelModel){
|
||||
|
||||
@ -48,13 +34,13 @@ public class StateLabelModel {
|
||||
if let modelFontStyle = model.fontStyle {
|
||||
self.disabledModel.fontStyle = modelFontStyle
|
||||
} else {
|
||||
model.fontStyle = StateLabelModel.defaultFontStyle
|
||||
model.fontStyle = FormLabelModel.defaultFontStyle
|
||||
}
|
||||
|
||||
//ensure the textColor is set
|
||||
//otherwise use the defaultEnabledTextColor
|
||||
if model.textColor == nil {
|
||||
model.textColor = StateLabelModel.defaultEnabledTextColor
|
||||
model.textColor = FormLabelModel.defaultEnabledTextColor
|
||||
}
|
||||
|
||||
//set the enabledModel to the model passed in
|
||||
@ -66,26 +52,30 @@ public class StateLabelModel {
|
||||
|
||||
public init(text: String){
|
||||
//create the enabled model
|
||||
self.enabledModel = LabelModel(fontStyle: StateLabelModel.defaultFontStyle, textColor: StateLabelModel.defaultEnabledTextColor)
|
||||
self.enabledModel = LabelModel(fontStyle: FormLabelModel.defaultFontStyle, textColor: FormLabelModel.defaultEnabledTextColor)
|
||||
self.enabledModel.text = text
|
||||
|
||||
//make sure the enabled & disabled text match
|
||||
self.disabledModel.text = self.enabledModel.text
|
||||
}
|
||||
|
||||
public var requiredModel: LabelModel {
|
||||
let required = LabelModel(fontStyle: model.fontStyle!, textColor: model.textColor!)
|
||||
if enabled {
|
||||
required.attributes = [LabelAttributeColorModel(FormLabelModel.defaultRequiredTextColor, model.text.count + 1, 8)]
|
||||
}
|
||||
required.text = "\(model.text) Optional"
|
||||
return required
|
||||
}
|
||||
|
||||
//methods
|
||||
public func reset(){
|
||||
self.state = .enabled
|
||||
self.enabled = true
|
||||
}
|
||||
|
||||
//set text for state
|
||||
public func set(text:String, for state: State){
|
||||
switch state {
|
||||
case .enabled, .disabled:
|
||||
self.enabledModel.text = text
|
||||
self.disabledModel.text = text
|
||||
case .error:
|
||||
self.errorLabelModel.text = text
|
||||
}
|
||||
public func set(text:String){
|
||||
self.enabledModel.text = text
|
||||
self.disabledModel.text = text
|
||||
}
|
||||
}
|
||||
@ -24,10 +24,14 @@
|
||||
case textColor
|
||||
}
|
||||
|
||||
public init(_ textColor: Color?, _ location: Int, _ length: Int){
|
||||
self.textColor = textColor
|
||||
super.init(location, length)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
textColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor)
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
public var fieldValue: String?
|
||||
public var enabled: Bool = true
|
||||
public var readOnly: Bool = false
|
||||
public var fieldKey: String?
|
||||
public var groupName: String = FormValidator.defaultGroupName
|
||||
public var baseValue: AnyHashable?
|
||||
@ -40,6 +41,8 @@
|
||||
case fieldValue
|
||||
case fieldKey
|
||||
case groupName
|
||||
case enabled
|
||||
case readOnly
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -57,6 +60,12 @@
|
||||
self.groupName = groupName
|
||||
}
|
||||
baseValue = fieldValue
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
if let readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) {
|
||||
self.readOnly = readOnly
|
||||
}
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
@ -67,5 +76,7 @@
|
||||
try container.encodeIfPresent(peakingArrowColor, forKey: .peakingArrowColor)
|
||||
try container.encodeIfPresent(analyticsData, forKey: .analyticsData)
|
||||
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(readOnly, forKey: .readOnly)
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +38,8 @@ import UIKit
|
||||
public var fieldKey: String?
|
||||
public var groupName: String = FormValidator.defaultGroupName
|
||||
public var enabled: Bool = true
|
||||
|
||||
public var readOnly: Bool = false
|
||||
|
||||
public var selectable = false
|
||||
public var selectedIndex: Int?
|
||||
|
||||
@ -87,6 +88,8 @@ import UIKit
|
||||
case fieldKey
|
||||
case selectable
|
||||
case selectedIndex
|
||||
case enabled
|
||||
case readOnly
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -120,10 +123,16 @@ import UIKit
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
self.groupName = groupName
|
||||
}
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
if let readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) {
|
||||
self.readOnly = readOnly
|
||||
}
|
||||
baseValue = formFieldValue()
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
@ -145,6 +154,8 @@ import UIKit
|
||||
try container.encode(index, forKey: .index)
|
||||
try container.encode(selectable, forKey: .selectable)
|
||||
try container.encode(selectedIndex, forKey: .selectedIndex)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(readOnly, forKey: .readOnly)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
//
|
||||
// ClearableModelProtocol.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Matt Bruce on 1/11/22.
|
||||
// Copyright © 2022 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol ClearableModelProtocol {
|
||||
func clear()
|
||||
}
|
||||
@ -13,7 +13,6 @@ import UIKit
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
open var model: MoleculeModelProtocol?
|
||||
|
||||
private var initialSetupPerformed = false
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
//
|
||||
// ClearFormFieldEffectModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Matt Bruce on 1/11/22.
|
||||
// Copyright © 2022 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ClearFormFieldEffectModel: FormFieldEffectProtocol {
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "clearFormFieldEffect"
|
||||
public var fieldKey: String = ""
|
||||
public var activatedRuleIds: [String]?
|
||||
public var rules: [RulesProtocol]
|
||||
|
||||
init(_ fieldKey: String, activatedRuleIds: [String], rules: [RulesProtocol]) {
|
||||
self.fieldKey = fieldKey
|
||||
self.activatedRuleIds = activatedRuleIds
|
||||
self.rules = rules
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case fieldKey
|
||||
case activatedRuleIds
|
||||
case rules
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.fieldKey = try typeContainer.decode(String.self, forKey: .fieldKey)
|
||||
self.activatedRuleIds = try typeContainer.decodeIfPresent([String].self, forKey: .activatedRuleIds)
|
||||
self.rules = try typeContainer.decodeModels(codingKey: .rules)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(fieldKey, forKey: .fieldKey)
|
||||
try container.encodeIfPresent(activatedRuleIds, forKey: .activatedRuleIds)
|
||||
try container.encodeModels(rules, forKey: .rules)
|
||||
}
|
||||
|
||||
public func setEffect(validity: Bool, field: FormFieldProtocol,form: FormValidator, group: FormGroupRule) {
|
||||
guard let field = field as? ClearableModelProtocol, validity else { return }
|
||||
field.clear()
|
||||
if let updateField = field as? UIUpdatableModelProtocol {
|
||||
updateField.updateUI?()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -16,11 +16,18 @@ public protocol FormFieldProtocol: FormItemProtocol {
|
||||
/// A place to store the initial value of the field for checking if the value has changed.
|
||||
var baseValue: AnyHashable? { get set }
|
||||
|
||||
///Bool to determine a state that is different from disabled. Readonly values will be sent
|
||||
///to the server where disabled fields are not
|
||||
var readOnly: Bool { get set }
|
||||
|
||||
/// Returns the value of the field. Used for validations and possibly for sending to server.
|
||||
func formFieldValue() -> AnyHashable?
|
||||
|
||||
}
|
||||
|
||||
extension FormFieldProtocol {
|
||||
|
||||
var baseValue: AnyHashable? { nil }
|
||||
|
||||
var readOnly: Bool { false }
|
||||
}
|
||||
|
||||
@ -111,11 +111,19 @@ import MVMCore
|
||||
/// - counter: keeps track of how many times causes another group validation
|
||||
/// - Returns: validity for the FormGroupRule.rules
|
||||
public func validateGroup(_ group: FormGroupRule, counter: Int = 0) throws -> Bool {
|
||||
let valid = group.validate(fields)
|
||||
let tuple = group.validate(fields)
|
||||
|
||||
group.rules.forEach { rule in
|
||||
for formKey in rule.fields {
|
||||
guard let formField = fields[formKey] as? FormRuleWatcherFieldProtocol,
|
||||
let fieldValidity = tuple.fieldValidity[formKey] else { continue }
|
||||
formField.setValidity(fieldValidity, rule: rule)
|
||||
}
|
||||
}
|
||||
|
||||
// Notify the group watchers of validity.
|
||||
for watcher in groupWatchers.filter({$0.groupName == group.groupName}) {
|
||||
watcher.setValidity(valid)
|
||||
watcher.setValidity(tuple.valid)
|
||||
}
|
||||
|
||||
var ruleChange = false
|
||||
@ -125,14 +133,14 @@ import MVMCore
|
||||
//get the fieldKey for the effect
|
||||
if let effected = fields[effect.fieldKey] {
|
||||
//get the validity
|
||||
let validity = effect.validate(fields)
|
||||
let effectTuple = effect.validate(fields)
|
||||
|
||||
//set the effect with the validation
|
||||
effect.setEffect(validity: validity, field: effected, form: self, group: group)
|
||||
effect.setEffect(validity: effectTuple.valid, field: effected, form: self, group: group)
|
||||
|
||||
//update the group form rules
|
||||
if let ruleIds = effect.activatedRuleIds {
|
||||
let didChange = self.updateRules(for: group, with: validity, for: effect.fieldKey, and: ruleIds)
|
||||
let didChange = self.updateRules(for: group, with: effectTuple.valid, for: effect.fieldKey, and: ruleIds)
|
||||
if(didChange) {
|
||||
ruleChange = didChange
|
||||
}
|
||||
@ -147,7 +155,7 @@ import MVMCore
|
||||
return try self.validateGroup(group, counter: counter + 1)
|
||||
}
|
||||
} else {
|
||||
return valid
|
||||
return tuple.valid
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -51,15 +51,10 @@ public class RuleEqualsIgnoreCaseModel: RulesProtocol {
|
||||
fieldValidity = false
|
||||
}
|
||||
|
||||
for formKey in fields {
|
||||
guard let formField = fieldMolecules[formKey] else { continue }
|
||||
(formField as? FormRuleWatcherFieldProtocol)?.setValidity(true, rule: self)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
previousValidity[formKey] = valid
|
||||
(formField as? FormRuleWatcherFieldProtocol)?.setValidity(valid, rule: self)
|
||||
}
|
||||
return (valid: valid, fieldValidity: previousValidity)
|
||||
}
|
||||
|
||||
@ -43,8 +43,6 @@ public class RuleEqualsModel: RulesProtocol {
|
||||
|
||||
if compareValue != formField.formFieldValue() {
|
||||
valid = false
|
||||
previousValidity[formKey] = valid
|
||||
(formField as? FormRuleWatcherFieldProtocol)?.setValidity(valid, rule: self)
|
||||
break
|
||||
} else {
|
||||
var fieldValidity = valid
|
||||
@ -52,8 +50,9 @@ public class RuleEqualsModel: RulesProtocol {
|
||||
if let validity = previousFieldValidity[formKey], !validity, fieldValidity {
|
||||
fieldValidity = false
|
||||
}
|
||||
(formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: self)
|
||||
}
|
||||
previousValidity[formKey] = valid
|
||||
|
||||
}
|
||||
return (valid: valid, fieldValidity: previousValidity)
|
||||
}
|
||||
|
||||
@ -53,7 +53,6 @@ public extension RulesProtocol {
|
||||
if let validity = previousFieldValidity[formKey], !validity, fieldValidity {
|
||||
fieldValidity = false
|
||||
}
|
||||
(formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: self)
|
||||
valid = valid && fieldValidity
|
||||
previousValidity[formKey] = fieldValidity
|
||||
}
|
||||
@ -66,12 +65,19 @@ public protocol RulesContainerProtocol{
|
||||
}
|
||||
|
||||
public extension RulesContainerProtocol {
|
||||
func validate(_ fields: [String: FormFieldProtocol]) -> Bool {
|
||||
/// This validation for Rules for the Validation or for Effects.
|
||||
/// - Parameters:
|
||||
/// - fields: Fields for the group
|
||||
/// - setValidity: Since this function is for validation, this bool determines if you should set the FormFields.setValidity for a rule.
|
||||
/// this method can be called for Form Validation and Effect Validation (this doesn't affect the submital of the form)
|
||||
/// - Returns: Tuple(valid, fieldValidity)
|
||||
/// - valid: bool for all rules
|
||||
/// - fieldValidity: accumulation of all fieldKey: valid
|
||||
func validate(_ fields: [String: FormFieldProtocol]) -> (valid: Bool, fieldValidity: [String:Bool] ) {
|
||||
// Validate each rule.
|
||||
var valid = true
|
||||
var previousValidity: [String: Bool] = [:]
|
||||
for rule in self.rules {
|
||||
|
||||
//validate the rule against the fields
|
||||
let tuple = rule.validate(fields, previousValidity)
|
||||
|
||||
@ -79,6 +85,6 @@ public extension RulesContainerProtocol {
|
||||
previousValidity = previousValidity.merging(tuple.fieldValidity) { (_, new) in new }
|
||||
valid = valid && tuple.valid
|
||||
}
|
||||
return valid
|
||||
return (valid: valid, fieldValidity: previousValidity)
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,5 +247,6 @@ open class CoreUIModelMapping: ModelMapping {
|
||||
ModelRegistry.register(DynamicRuleFormFieldEffectModel.self)
|
||||
ModelRegistry.register(DisableFormFieldEffectModel.self)
|
||||
ModelRegistry.register(HideFormFieldEffectModel.self)
|
||||
ModelRegistry.register(ClearFormFieldEffectModel.self)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user