diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m index 57470bf9..fa719012 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m @@ -17,9 +17,10 @@ @import MVMCore.MVMCoreGetterUtility; @import MVMCore.NSDictionary_MFConvenience; -@interface PrimaryButton() +@interface PrimaryButton() @property (nonatomic) BOOL validationRequired; +@property (nonatomic, strong) NSArray *requiredFieldsList; @property (nonatomic) BOOL smallButton; @property (assign, nonatomic) BOOL tinyButton; @property (nonatomic) CGFloat sizeForSizing; @@ -697,6 +698,7 @@ self.disabledBorderColor = [UIColor mfGetColorForHex:color]; } self.validationRequired = [json boolForKey:@"validationRequired"]; + self.requiredFieldsList = [json array:@"requiredFields"]; NSString *size = [json string:@"size"]; if ([size isEqualToString:@"small"]) { @@ -773,7 +775,11 @@ } } -#pragma mark - FormValidationProtocol +#pragma mark - FormValidationEnableDisableProtocol + +- (NSArray *)requiredFields { + return self.requiredFieldsList; +} - (void)enableField:(BOOL)enable { if (!self.validationRequired) { diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField.h b/MVMCoreUI/Atoms/TextFields/MFTextField.h index 72adf682..3e229092 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField.h +++ b/MVMCoreUI/Atoms/TextFields/MFTextField.h @@ -43,9 +43,10 @@ @property (nonatomic,getter=isEnabled) BOOL enabled; // To set the placeholder and text -@property (nullable, weak, nonatomic) NSString *text; -@property (nullable, weak, nonatomic) NSString *formText; -@property (nullable, weak, nonatomic) NSString *fieldKey; +@property (nullable, strong, nonatomic) NSString *text; +@property (nullable, strong, nonatomic) NSString *formText; +@property (nullable, strong, nonatomic) NSString *fieldKey; +@property (nullable, strong, nonatomic) NSString *groupName; @property (nullable, weak, nonatomic) NSString *placeholder; // will move out in Feb release diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField.m b/MVMCoreUI/Atoms/TextFields/MFTextField.m index ba68c0ed..0e9be054 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField.m +++ b/MVMCoreUI/Atoms/TextFields/MFTextField.m @@ -18,7 +18,7 @@ @import MVMCore.NSDictionary_MFConvenience; @import MVMCore.MVMCoreJSONConstants; -@interface MFTextField() +@interface MFTextField() @property (strong, nonatomic) UIColor *customPlaceHolderColor; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *separatorHeightConstraint; @@ -303,28 +303,20 @@ return; } - NSString *string = [map string:KeyLabel]; - if (string.length > 0) { - self.formText = string; - } - string = [map string:KeyValue]; - if (string.length > 0) { + self.formText = [map string:KeyLabel];; + self.groupName = [map string:@"groupName"]; + self.errMessage = [map string:KeyErrorMessage]; + self.fieldKey = [map string:KeyFieldKey]; + + NSString *string = [map stringForKey:KeyValue]; + if (string.length) { self.text = string; } + string = [map stringForKey:KeyDisable]; if ([string isEqual:StringY] || [map boolForKey:KeyDisable]) { [self enable:NO]; } - string = [map string:KeyErrorMessage]; - if (string.length > 0) { - self.errMessage = string; - } - - // key used to send text value to server - string = [map string:KeyFieldKey]; - if (string.length > 0) { - self.fieldKey = string; - } string = [map string:KeyType]; if ([string isEqualToString:@"dropDown"]) { @@ -588,5 +580,9 @@ - (nullable id)formFieldValue { return self.text; } - + +- (NSString * _Nullable)formFieldGroupName { + return self.groupName; +} + @end diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m index 2b5a7f37..f31aace3 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m @@ -21,7 +21,7 @@ static const CGFloat FaultTolerance = 20.f; static const CGFloat CheckBoxHeightWidth = 18.0; -@interface MVMCoreUICheckBox () +@interface MVMCoreUICheckBox () @property (nonatomic, readwrite) BOOL isSelected; @property (weak, nonatomic) UIView *checkedSquare; diff --git a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift index b593a503..0af41b42 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift @@ -12,16 +12,26 @@ import Foundation // Getter method to get the FormValidator form the delegate (Mostly from the parent View Controller) @objc optional func formValidatorModel() -> FormValidator? - +} + +@objc public protocol FormValidationFormFieldProtocol: FormValidationProtocol { // Used to check the validity of the field, to enable/disable the primary button. - @objc optional func isValidField() -> Bool + @objc func isValidField() -> Bool + // The Field name key value pair for sending to server + @objc func formFieldName() -> String? + + // Returns the group name for validation + @objc func formFieldGroupName() -> String? + + // The Field value key value pair for sending to server + @objc func formFieldValue() -> Any? +} + +@objc public protocol FormValidationEnableDisableProtocol: FormValidationProtocol { // Based on the isValidField(), the fields which needs to be enabled can call this method @objc optional func enableField(_ enable: Bool) - // The Field name key value pair for sending to server - @objc optional func formFieldName() -> String? - - // The Field value key value pair for sending to server - @objc optional func formFieldValue() -> Any? + // Returns the list of field keys required to enable/disable + @objc optional func requiredFields() -> [String]? } diff --git a/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift b/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift index bb9885ab..4c4945a4 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift @@ -16,9 +16,9 @@ import Foundation @objc func getFormParams() -> [String: Any] { var extraParam: [String: Any] = [:] MVMCoreDispatchUtility.performSyncBlock(onMainThread: { - for molecule in self.molecules { - if let formFieldName = molecule.formFieldName?(), - let formFieldValue = molecule.formFieldValue?() { + for molecule in self.fieldMolecules { + if let formFieldName = molecule.formFieldName(), + let formFieldValue = molecule.formFieldValue() { extraParam[formFieldName] = formFieldValue } } diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 91928f3e..821db784 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -8,16 +8,22 @@ import Foundation import UIKit +import MVMCore @objcMembers public class FormValidator: NSObject { var delegate: FormValidationProtocol? - var molecules: [FormValidationProtocol] = [] - var extraValidationBlock: (() -> Bool)? + var fieldMolecules: [FormValidationFormFieldProtocol] = [] + var enableDisableMolecules: [FormValidationEnableDisableProtocol] = [] var radioButtonsModelByGroup: [String: RadioButtonModel] = [:] public func insertMolecule(_ molecule: FormValidationProtocol) { - molecules.append(molecule) + if let molecule = molecule as? FormValidationFormFieldProtocol { + fieldMolecules.append(molecule) + } + if let molecule = molecule as? FormValidationEnableDisableProtocol { + enableDisableMolecules.append(molecule) + } } public static func enableByValidationWith(delegate: FormValidationProtocol?) { @@ -39,18 +45,25 @@ import UIKit } public func enableByValidation() { - var valid = true - for molecule in molecules { - valid = valid && (molecule.isValidField?() ?? true) + var groupValue: [String: Bool] = [:] + for molecule in fieldMolecules { + let valid = molecule.isValidField() + if let grouName = molecule.formFieldGroupName() { + groupValue[grouName] = valid && (groupValue[grouName] ?? true) + } } - let enableField = valid && (extraValidationBlock?() ?? true) - shouldEnable(enableField) + shouldEnable(groupValue) } - public func shouldEnable(_ enable: Bool) { - for molecule in molecules { - molecule.enableField?(enable) + public func shouldEnable(_ groupValue: [String: Bool]) { + for molecule in enableDisableMolecules { + var valid = false + for groupName in molecule.requiredFields?() ?? [] { + valid = groupValue[groupName] ?? false + } + molecule.enableField?(valid) } } + } diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index acd5f016..b95b2ab7 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -9,9 +9,9 @@ import UIKit -@objcMembers open class RadioButton: ViewConstrainingView { +@objcMembers open class RadioButton: ViewConstrainingView, FormValidationFormFieldProtocol { - let radioButton = MFRadioButton() + public let radioButton = MFRadioButton() var delegateObject: MVMCoreUIDelegateObject? var dummyButton: MFCustomButton? let label = Label() @@ -20,10 +20,11 @@ import UIKit var formValue: Bool? var isRequired: Bool = false var radioButtonModel: RadioButtonModel? + lazy var groupName: String? = { [unowned self] in - return json?.optionalStringForKey("groupName") ?? json?.optionalStringForKey("fieldKey") + return json?.optionalStringForKey("radioGroupName") ?? json?.optionalStringForKey("fieldKey") }() // MARK: - Inits @@ -106,6 +107,22 @@ import UIKit FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) changeAccessibilityLabel() } + + public func isValidField() -> Bool { + return radioButton.isSelected + } + + public func formFieldName() -> String? { + return json?.optionalStringForKey("fieldKey") + } + + public func formFieldGroupName() -> String? { + return json?.optionalStringForKey("radioGroupName") + } + + public func formFieldValue() -> Any? { + return radioButton.isSelected + } } // MARK: - MVMCoreUIMoleculeViewProtocol diff --git a/MVMCoreUI/Molecules/RadioButtonModel.swift b/MVMCoreUI/Molecules/RadioButtonModel.swift index 40238307..812ea36a 100644 --- a/MVMCoreUI/Molecules/RadioButtonModel.swift +++ b/MVMCoreUI/Molecules/RadioButtonModel.swift @@ -12,14 +12,16 @@ import UIKit @objcMembers public class RadioButtonModel: NSObject { private var selectedRadioButton: RadioButton? + private var fieldGroupName: String? public static func setupForRadioButtonGroup(radioButton: RadioButton, formValidator: FormValidator?) -> RadioButtonModel { guard let groupName = radioButton.groupName, let formValidator = formValidator else { return RadioButtonModel() } - + let radioButtonModel = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonModel() + radioButtonModel.fieldGroupName = radioButton.formFieldGroupName() formValidator.radioButtonsModelByGroup[groupName] = radioButtonModel return radioButtonModel } @@ -32,7 +34,11 @@ import UIKit } // MARK: - FormValidationProtocol -extension RadioButtonModel: FormValidationProtocol { +extension RadioButtonModel: FormValidationFormFieldProtocol { + public func formFieldGroupName() -> String? { + return selectedRadioButton?.formFieldGroupName() ?? self.fieldGroupName + } + // Used to check the validity of the field, to enable/disable the primary button. @objc public func isValidField() -> Bool { return selectedRadioButton != nil ? true : false diff --git a/MVMCoreUI/Molecules/Switch.swift b/MVMCoreUI/Molecules/Switch.swift index 5b23b1d5..8cb19909 100644 --- a/MVMCoreUI/Molecules/Switch.swift +++ b/MVMCoreUI/Molecules/Switch.swift @@ -8,7 +8,7 @@ import UIKit -@objcMembers public class Switch: ViewConstrainingView, FormValidationProtocol{ +@objcMembers public class Switch: ViewConstrainingView, FormValidationFormFieldProtocol { public var mvmSwitch = MVMCoreUISwitch() var isRequired = false var delegateObject: DelegateObject? @@ -76,6 +76,10 @@ import UIKit return mvmSwitch.isOn } + public func formFieldGroupName() -> String? { + return json?.optionalStringForKey("groupName") + } + public override func needsToBeConstrained() -> Bool { return true } diff --git a/MVMCoreUI/Molecules/SwitchLineItem.swift b/MVMCoreUI/Molecules/SwitchLineItem.swift index 8c15e8ec..54860158 100644 --- a/MVMCoreUI/Molecules/SwitchLineItem.swift +++ b/MVMCoreUI/Molecules/SwitchLineItem.swift @@ -8,7 +8,9 @@ import UIKit -@objcMembers public class SwitchLineItem: ViewConstrainingView, FormValidationProtocol{ +@objcMembers public class SwitchLineItem: ViewConstrainingView, FormValidationFormFieldProtocol { + + public var mvmSwitch = Switch() public var label = Label() public var leftContainerView = UIView() @@ -116,6 +118,23 @@ import UIKit public override func alignment() -> UIStackView.Alignment { return UIStackView.Alignment.leading } + + + public func isValidField() -> Bool { + return mvmSwitch.isValidField() + } + + public func formFieldName() -> String? { + return mvmSwitch.formFieldName() + } + + public func formFieldGroupName() -> String? { + return mvmSwitch.formFieldGroupName() + } + + public func formFieldValue() -> Any? { + return mvmSwitch.formFieldValue() + } }