Merge branch 'feature/molecule_testfields' into 'develop'
Feature/molecule testfields See merge request BPHV_MIPS/mvm_core_ui!16
This commit is contained in:
commit
e61ef45913
@ -7,8 +7,13 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0105618D224BBE7700E1557D /* FormValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618A224BBE7700E1557D /* FormValidator.swift */; };
|
||||
0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */; };
|
||||
0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */; };
|
||||
0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198F79E225679870066C936 /* FormValidationProtocol.swift */; };
|
||||
01DF55E021F8FAA800CC099B /* MFTextFieldListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */; };
|
||||
01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */; };
|
||||
01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D206997721FB8A0B00CAE0DE /* MVMCoreUINavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D206997821FB8A0B00CAE0DE /* MVMCoreUINavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = D206997621FB8A0B00CAE0DE /* MVMCoreUINavigationController.m */; };
|
||||
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; };
|
||||
@ -158,6 +163,10 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0105618A224BBE7700E1557D /* FormValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidator.swift; sourceTree = "<group>"; };
|
||||
0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+TextFields.swift"; sourceTree = "<group>"; };
|
||||
0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+FormParams.swift"; sourceTree = "<group>"; };
|
||||
0198F79E225679870066C936 /* FormValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidationProtocol.swift; sourceTree = "<group>"; };
|
||||
01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MFTextFieldListView.swift; sourceTree = "<group>"; };
|
||||
01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldListFormViewController.swift; sourceTree = "<group>"; };
|
||||
D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUINavigationController.h; sourceTree = "<group>"; };
|
||||
@ -325,6 +334,17 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
01C74D87224298E2009C25A3 /* FormUIHelpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0198F79E225679870066C936 /* FormValidationProtocol.swift */,
|
||||
0105618A224BBE7700E1557D /* FormValidator.swift */,
|
||||
0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */,
|
||||
0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */,
|
||||
);
|
||||
path = FormUIHelpers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D22D1F582204D2590077CEC0 /* LegacyControllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -358,6 +378,7 @@
|
||||
D29DF0CE21E404D4003B2FB9 /* MVMCoreUI */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
01C74D87224298E2009C25A3 /* FormUIHelpers */,
|
||||
D29DF31421ECECA7003B2FB9 /* SupportingFiles */,
|
||||
D29DF27021E79B2C003B2FB9 /* OtherHandlers */,
|
||||
D29DF13A21E68682003B2FB9 /* Utility */,
|
||||
@ -728,6 +749,7 @@
|
||||
D2C5001D21F8EE67001DA659 /* LabelWithInternalButton.h in Headers */,
|
||||
D29DF11621E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h in Headers */,
|
||||
D29DF17721E69E1F003B2FB9 /* MFTextButton.h in Headers */,
|
||||
01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */,
|
||||
D29DF16221E69996003B2FB9 /* MFViewController.h in Headers */,
|
||||
D29DF13121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h in Headers */,
|
||||
D29DF2C421E7BF57003B2FB9 /* MFTabBarSwipeAnimator.h in Headers */,
|
||||
@ -866,6 +888,7 @@
|
||||
D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */,
|
||||
D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */,
|
||||
D282AACB2243C61700C46919 /* ButtonView.swift in Sources */,
|
||||
0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */,
|
||||
D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */,
|
||||
D29DF18121E69E50003B2FB9 /* MFView.m in Sources */,
|
||||
D29DF18321E69E54003B2FB9 /* SeparatorView.m in Sources */,
|
||||
@ -886,6 +909,7 @@
|
||||
D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */,
|
||||
D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */,
|
||||
D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */,
|
||||
0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */,
|
||||
D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */,
|
||||
D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */,
|
||||
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */,
|
||||
@ -899,11 +923,13 @@
|
||||
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
|
||||
D2C5001E21F8EE67001DA659 /* LabelWithInternalButton.m in Sources */,
|
||||
D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */,
|
||||
0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */,
|
||||
D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */,
|
||||
D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */,
|
||||
D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */,
|
||||
D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */,
|
||||
D2A514592211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m in Sources */,
|
||||
0105618D224BBE7700E1557D /* FormValidator.swift in Sources */,
|
||||
D22D1F1B220341F60077CEC0 /* MVMCoreUICheckBox.m in Sources */,
|
||||
D29DF2CB21E7BFCC003B2FB9 /* MFSizeThreshold.m in Sources */,
|
||||
D29770F521F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m in Sources */,
|
||||
|
||||
@ -12,24 +12,24 @@
|
||||
#import "MVMCoreUISplitViewController.h"
|
||||
#import "MFStyler.h"
|
||||
#import "UIColor+MFConvenience.h"
|
||||
#import <MVMCoreUI/MVMCoreUI-Swift.h>
|
||||
@import MVMCore.MVMCoreDispatchUtility;
|
||||
@import MVMCore.MVMCoreGetterUtility;
|
||||
@import MVMCore.NSDictionary_MFConvenience;
|
||||
|
||||
@interface PrimaryButton ()
|
||||
|
||||
@interface PrimaryButton() <FormValidationProtocol>
|
||||
|
||||
@property (nonatomic) BOOL validationRequired;
|
||||
@property (nonatomic) BOOL smallButton;
|
||||
@property (assign, nonatomic) BOOL tinyButton;
|
||||
@property (nonatomic) CGFloat sizeForSizing;
|
||||
|
||||
@property (weak, nonatomic) NSLayoutConstraint *height;
|
||||
@property (weak, nonatomic) NSLayoutConstraint *width;
|
||||
|
||||
@property (strong, nonatomic) NSArray <MFTextField *>*textFields;
|
||||
|
||||
@property (strong, nonatomic) NSMutableArray <MFTextField *>*textFields;
|
||||
@property (nonatomic, readwrite, assign) PrimaryButtonType primaryButtonType;
|
||||
|
||||
@property (nonatomic) CGFloat sizeForSizing;
|
||||
|
||||
@end
|
||||
|
||||
@implementation PrimaryButton
|
||||
@ -645,6 +645,9 @@
|
||||
}
|
||||
|
||||
- (void)setWithJSON:(NSDictionary *)json delegate:(NSObject *)delegate additionalData:(nullable NSDictionary *)additionalData {
|
||||
|
||||
[FormValidator setupValidationWithMolecule:self delegate:(id<FormValidationProtocol>)delegate];
|
||||
|
||||
self.primaryButtonType = PrimaryButtonTypeCustom;
|
||||
NSString *color = [json string:@"fillColor"];
|
||||
if (color) {
|
||||
@ -666,6 +669,8 @@
|
||||
if ((color = [json string:@"disabledBorderColor"])) {
|
||||
self.disabledBorderColor = [UIColor mfGetColorForHex:color];
|
||||
}
|
||||
self.validationRequired = [json boolForKey:@"validationRequired"];
|
||||
|
||||
[self setAsSmallButton:[json boolForKey:@"small"]];
|
||||
[self setWithActionMap:json actionDelegate:([delegate conformsToProtocol:@protocol(MVMCoreActionDelegateProtocol)] ? (NSObject <MVMCoreActionDelegateProtocol>*)delegate : nil) additionalData:additionalData buttonDelegate:([delegate conformsToProtocol:@protocol(ButtonDelegateProtocol)] ? (id <ButtonDelegateProtocol>)delegate : nil)];
|
||||
}
|
||||
@ -673,6 +678,7 @@
|
||||
#pragma mark - Handling Validations
|
||||
|
||||
- (void)setEnabledByValidity {
|
||||
|
||||
__block BOOL valid = YES;
|
||||
[self.textFields enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
if (!((MFTextField *)obj).valid) {
|
||||
@ -680,7 +686,7 @@
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
|
||||
|
||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||
self.enabled = valid && (self.extraValidationBlock ? self.extraValidationBlock() : YES);
|
||||
}];
|
||||
@ -692,7 +698,7 @@
|
||||
field.mfTextFieldDelegate = nil;
|
||||
}
|
||||
}
|
||||
self.textFields = textFields;
|
||||
self.textFields = [textFields mutableCopy];
|
||||
|
||||
for (MFTextField *field in self.textFields) {
|
||||
field.mfTextFieldDelegate = self;
|
||||
@ -708,7 +714,7 @@
|
||||
field.mfTextFieldDelegate = nil;
|
||||
}
|
||||
}
|
||||
self.textFields = textFields;
|
||||
self.textFields = [textFields mutableCopy];
|
||||
|
||||
for (MFTextField *field in self.textFields) {
|
||||
field.mfTextFieldDelegate = self;
|
||||
@ -733,4 +739,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - FormValidationProtocol
|
||||
|
||||
- (void)enableField:(BOOL)enable {
|
||||
if (!self.validationRequired) {
|
||||
self.enabled = YES;
|
||||
} else {
|
||||
self.enabled = enable;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
|
||||
@end
|
||||
|
||||
@interface MFTextField : MFView
|
||||
@interface MFTextField : MFView <MVMCoreUIMoleculeViewProtocol>
|
||||
|
||||
@property (nullable, weak, nonatomic) UIView *view;
|
||||
|
||||
@ -127,4 +127,8 @@
|
||||
|
||||
- (void)setAccessibilityString:(nullable NSString *)accessibilityString;
|
||||
|
||||
// For Validator Protocol
|
||||
- (nullable NSString *)formFieldName;
|
||||
- (nullable id)formFieldValue;
|
||||
|
||||
@end
|
||||
|
||||
@ -15,17 +15,26 @@
|
||||
#import "MFLabel.h"
|
||||
#import "MVMCoreUIUtility.h"
|
||||
#import "MVMCoreUIConstants.h"
|
||||
#import <MVMCoreUI/MVMCoreUI-Swift.h>
|
||||
@import MVMCore.MVMCoreDispatchUtility;
|
||||
@import MVMCore.NSDictionary_MFConvenience;
|
||||
@import MVMCore.MVMCoreJSONConstants;
|
||||
|
||||
@interface MFTextField()
|
||||
@interface MFTextField() <FormValidationProtocol>
|
||||
|
||||
@property (strong, nonatomic) UIColor *customPlaceHolderColor;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *separatorHeightConstraint;
|
||||
@property (strong, nonatomic) UIBezierPath *borderPath;
|
||||
@property (strong, nonatomic) NSCalendar *calendar;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textContainerLeftPin;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *errorLableLeftPin;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *formLabelLeftPin;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textContainerRightPin;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *errorLableRightPin;
|
||||
@property (nonatomic) BOOL isMolecule;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MFTextField
|
||||
@ -38,6 +47,12 @@
|
||||
self.label.font = [MFStyler fontForTextFieldUnderLabel];
|
||||
[MFStyler styleTextField:self.textField];
|
||||
[self.dashLine updateView:size];
|
||||
|
||||
if (self.isMolecule) {
|
||||
[self setHorizontalPadding:[MFStyler defaultHorizontalPaddingForSize:size]];
|
||||
} else {
|
||||
[self setHorizontalPadding:0];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@ -53,10 +68,7 @@
|
||||
view.frame = self.frame;
|
||||
[self addSubview:view];
|
||||
|
||||
// self.textFieldContainerView.layer.borderWidth = 1;
|
||||
// self.textFieldContainerView.layer.borderColor = [UIColor mfSilver].CGColor;
|
||||
self.textField.font = [MFStyler fontForTextField];
|
||||
|
||||
self.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
|
||||
self.formLabel.font = [MFStyler fontB3];
|
||||
@ -104,37 +116,7 @@
|
||||
+ (nullable instancetype)mfTextFieldWithMap:(nullable NSDictionary *)map bothDelegates:(nullable id<UITextFieldDelegate, MFTextFieldDelegate>)delegate {
|
||||
MFTextField *textField = [self mfTextField];
|
||||
textField.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[textField setWithMap:map bothDelegates:delegate];
|
||||
if (map.count > 0) {
|
||||
|
||||
// Can add these to the set with map function later after verifying
|
||||
NSString *string = [map string:@"fieldKey"];
|
||||
if (string.length > 0) {
|
||||
textField.fieldKey = string;
|
||||
}
|
||||
|
||||
string = [map string:KeyType];
|
||||
if ([string isEqualToString:@"dropDown"]) {
|
||||
[[textField dropDownCarrotLabel] setHidden:NO];
|
||||
[textField setHasDropDown:YES];
|
||||
} else if ([string isEqualToString:@"password"]) {
|
||||
textField.textField.secureTextEntry = YES;
|
||||
} else if ([string isEqualToString:@"number"]) {
|
||||
textField.textField.keyboardType = UIKeyboardTypeNumberPad;
|
||||
} else if ([string isEqualToString:@"email"]) {
|
||||
textField.textField.keyboardType = UIKeyboardTypeEmailAddress;
|
||||
}
|
||||
|
||||
string = [map string:@"regex"];
|
||||
if (string.length > 0) {
|
||||
textField.validationBlock = ^BOOL(NSString * _Nullable enteredValue) {
|
||||
return [MVMCoreUIUtility validateString:enteredValue withRegularExpression:string];
|
||||
};
|
||||
} else {
|
||||
[textField setDefaultValidationBlock];
|
||||
}
|
||||
}
|
||||
|
||||
[textField setWithJSON:map delegate:delegate additionalData:nil];
|
||||
return textField;
|
||||
}
|
||||
|
||||
@ -319,25 +301,55 @@
|
||||
}
|
||||
|
||||
- (void)setWithMap:(nullable NSDictionary *)map bothDelegates:(nullable id<UITextFieldDelegate, MFTextFieldDelegate>)delegate {
|
||||
if (map.count > 0) {
|
||||
NSString *string = [map string:KeyLabel];
|
||||
if (string.length > 0) {
|
||||
self.formText = string;
|
||||
}
|
||||
string = [map string:KeyValue];
|
||||
if (string.length > 0) {
|
||||
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;
|
||||
}
|
||||
[MVMCoreUICommonViewsUtility addDismissToolbar:self.textField delegate:delegate];
|
||||
[self setBothTextFieldDelegates:delegate];
|
||||
if (map.count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
[MVMCoreUICommonViewsUtility addDismissToolbar:self.textField delegate:delegate];
|
||||
[self setBothTextFieldDelegates:delegate];
|
||||
|
||||
NSString *string = [map string:KeyLabel];
|
||||
if (string.length > 0) {
|
||||
self.formText = string;
|
||||
}
|
||||
string = [map string:KeyValue];
|
||||
if (string.length > 0) {
|
||||
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:@"fieldKey"];
|
||||
if (string.length > 0) {
|
||||
self.fieldKey = string;
|
||||
}
|
||||
|
||||
string = [map string:KeyType];
|
||||
if ([string isEqualToString:@"dropDown"]) {
|
||||
[[self dropDownCarrotLabel] setHidden:NO];
|
||||
[self setHasDropDown:YES];
|
||||
} else if ([string isEqualToString:@"password"]) {
|
||||
self.textField.secureTextEntry = YES;
|
||||
} else if ([string isEqualToString:@"number"]) {
|
||||
self.textField.keyboardType = UIKeyboardTypeNumberPad;
|
||||
} else if ([string isEqualToString:@"email"]) {
|
||||
self.textField.keyboardType = UIKeyboardTypeEmailAddress;
|
||||
}
|
||||
|
||||
string = [map string:@"regex"];
|
||||
if (string.length) {
|
||||
self.validationBlock = ^BOOL(NSString * _Nullable enteredValue) {
|
||||
return [MVMCoreUIUtility validateString:enteredValue withRegularExpression:string];
|
||||
};
|
||||
} else {
|
||||
[self setDefaultValidationBlock];
|
||||
}
|
||||
}
|
||||
|
||||
@ -356,6 +368,16 @@
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setHorizontalPadding:(CGFloat)padding {
|
||||
self.textContainerLeftPin.constant = padding;
|
||||
self.errorLableLeftPin.constant = padding;
|
||||
self.formLabelLeftPin.constant = padding;
|
||||
|
||||
self.textContainerRightPin.constant = padding;
|
||||
self.errorLableRightPin.constant = padding;
|
||||
self.formLabelRightPin.constant = padding;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self setBothTextFieldDelegates:nil];
|
||||
}
|
||||
@ -530,4 +552,31 @@
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - MVMCoreUIMoleculeViewProtocol
|
||||
|
||||
- (void)setAsMolecule {
|
||||
self.isMolecule = YES;
|
||||
}
|
||||
|
||||
- (void)setWithJSON:(NSDictionary *)json delegate:(nullable id<UITextFieldDelegate, MFTextFieldDelegate>)delegate additionalData:(NSDictionary *)additionalData {
|
||||
[FormValidator setupValidationWithMolecule:self delegate:(id<FormValidationProtocol>)delegate];
|
||||
FormValidator *formValidator = [FormValidator getFormValidatorForDelegate:(id<FormValidationProtocol>)delegate];
|
||||
[self setWithMap:json bothDelegates:formValidator];
|
||||
}
|
||||
|
||||
#pragma mark - FormValidationProtocol
|
||||
|
||||
|
||||
- (BOOL)isValidField {
|
||||
return self.valid;
|
||||
}
|
||||
|
||||
- (nullable NSString *)formFieldName {
|
||||
return self.fieldKey;
|
||||
}
|
||||
|
||||
- (nullable id)formFieldValue {
|
||||
return self.text;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -14,11 +14,16 @@
|
||||
<outlet property="dashLine" destination="hw1-Eo-Szn" id="WCs-FF-LCg"/>
|
||||
<outlet property="dropDownCarrotLabel" destination="XuL-hz-X9C" id="Kv1-Pd-Kra"/>
|
||||
<outlet property="dropDownCarrotWidth" destination="DJA-00-1ne" id="SHb-1H-EZD"/>
|
||||
<outlet property="errorLableLeftPin" destination="8pf-sH-2Ct" id="nhS-H8-RKZ"/>
|
||||
<outlet property="errorLableRightPin" destination="I5y-Go-vVq" id="TN8-Bi-GEP"/>
|
||||
<outlet property="formLabel" destination="8zH-YN-qag" id="him-Et-eoN"/>
|
||||
<outlet property="formLabelLeftPin" destination="gLb-br-rma" id="K1a-jV-qMg"/>
|
||||
<outlet property="formLabelRightPin" destination="Gkx-Zw-C4C" id="7Nl-BF-Jjo"/>
|
||||
<outlet property="label" destination="2KH-5l-kKu" id="bld-nC-XdN"/>
|
||||
<outlet property="separatorHeightConstraint" destination="f1r-3b-nqr" id="Zzz-yD-9zP"/>
|
||||
<outlet property="separatorView" destination="TDi-WU-Tyf" id="5zT-hU-Myw"/>
|
||||
<outlet property="textContainerLeftPin" destination="sUf-uc-1Ta" id="k9f-nH-EO3"/>
|
||||
<outlet property="textContainerRightPin" destination="BkX-rc-bYe" id="wKx-IQ-50w"/>
|
||||
<outlet property="textField" destination="fQx-7g-t8O" id="FKe-6f-DxN"/>
|
||||
<outlet property="textFieldContainerView" destination="vFx-S6-fbH" id="85j-fY-e2P"/>
|
||||
</connections>
|
||||
|
||||
@ -36,9 +36,10 @@
|
||||
#import "MVMCoreUILoggingHandler.h"
|
||||
#import "MVMCoreUITabBarPageControlViewController.h"
|
||||
#import "MVMCoreUINavigationController.h"
|
||||
#import <MVMCoreUI/MVMCoreUI-Swift.h>
|
||||
@import MVMAnimationFramework;
|
||||
|
||||
@interface MFViewController ()
|
||||
@interface MFViewController() <FormValidationProtocol>
|
||||
|
||||
// A flag for if this view controller is observing for cache updates or not.
|
||||
@property (nonatomic) BOOL observingForResponseJSONUpdates;
|
||||
@ -52,10 +53,19 @@
|
||||
// title view for navigation bar, used for custom navigation titles
|
||||
@property (weak, nonatomic) UILabel *titleLabel;
|
||||
|
||||
@property (strong, nonatomic) FormValidator *formValidator;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MFViewController
|
||||
|
||||
- (FormValidator *)formValidatorModel {
|
||||
if (self.formValidator == nil) {
|
||||
self.formValidator = [FormValidator new];
|
||||
}
|
||||
return self.formValidator;
|
||||
}
|
||||
|
||||
- (void)dismiss {
|
||||
if (self.presentingViewController) {
|
||||
[[MVMCoreNavigationHandler sharedNavigationHandler] dismissViewController:self animated:YES];
|
||||
@ -241,9 +251,8 @@
|
||||
if (page) {
|
||||
self.loadObject.pageJSON = page;
|
||||
}
|
||||
|
||||
[self newDataBuildScreen];
|
||||
self.needToUpdateUI = YES;
|
||||
|
||||
[self updateUI];
|
||||
[self.view setNeedsLayout];
|
||||
[self.view layoutIfNeeded];
|
||||
}];
|
||||
@ -400,11 +409,9 @@
|
||||
[self initialLoad];
|
||||
}
|
||||
|
||||
// Since we have new data, build stuff for the screen.
|
||||
[self newDataBuildScreen];
|
||||
// Since we have new data, build stuff for the screen and update the ui once the screen is done laying out.
|
||||
[self updateUI];
|
||||
|
||||
// Update the UI after the view is loaded.
|
||||
self.needToUpdateUI = YES;
|
||||
self.needToupdateUIOnScreenSizeChanges = YES;
|
||||
|
||||
if (UIAccessibilityIsVoiceOverRunning()) {
|
||||
@ -416,6 +423,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateUI {
|
||||
[self newDataBuildScreen];
|
||||
[self.formValidator enableByValidation];
|
||||
self.needToUpdateUI = YES;
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
@ -587,6 +600,7 @@
|
||||
[[MVMCoreUISession sharedGlobal].splitViewController.rightPanel willOpenWithActionInformation:actionInformation];
|
||||
}
|
||||
|
||||
[self.formValidator addFormParamsWithRequestParameters:requestParameters];
|
||||
requestParameters.parentPageType = [self.loadObject.pageJSON stringForKey:@"parentPageType"];
|
||||
|
||||
[[MVMCoreLoadHandler sharedGlobal] loadRequest:requestParameters dataForPage:additionalData delegate:self];
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
import UIKit
|
||||
import MVMAnimationFramework
|
||||
|
||||
public class ThreeLayerViewController: ProgrammaticScrollViewController {
|
||||
open class ThreeLayerViewController: ProgrammaticScrollViewController {
|
||||
|
||||
// The three main views
|
||||
var topView: UIView?
|
||||
@ -22,8 +22,8 @@ public class ThreeLayerViewController: ProgrammaticScrollViewController {
|
||||
|
||||
private var safeAreaView: UIView?
|
||||
private var heightConstraint: NSLayoutConstraint?
|
||||
|
||||
public override func updateViews() {
|
||||
|
||||
open override func updateViews() {
|
||||
super.updateViews()
|
||||
let width = view.bounds.width
|
||||
if let topView = topView as? MVMCoreViewProtocol {
|
||||
@ -37,7 +37,7 @@ public class ThreeLayerViewController: ProgrammaticScrollViewController {
|
||||
}
|
||||
}
|
||||
|
||||
public override func updateViewConstraints() {
|
||||
open override func updateViewConstraints() {
|
||||
super.updateViewConstraints()
|
||||
guard let scrollView = scrollView else {
|
||||
return
|
||||
@ -50,7 +50,7 @@ public class ThreeLayerViewController: ProgrammaticScrollViewController {
|
||||
}
|
||||
}
|
||||
|
||||
public override func loadView() {
|
||||
open override func loadView() {
|
||||
super.loadView()
|
||||
// The height is used to keep the bottom view at the bottom.
|
||||
if let contentView = contentView, let scrollView = scrollView {
|
||||
@ -59,7 +59,7 @@ public class ThreeLayerViewController: ProgrammaticScrollViewController {
|
||||
}
|
||||
}
|
||||
|
||||
public override func newDataBuildScreen() {
|
||||
open override func newDataBuildScreen() {
|
||||
super.newDataBuildScreen()
|
||||
|
||||
// Removes the views
|
||||
@ -78,27 +78,27 @@ public class ThreeLayerViewController: ProgrammaticScrollViewController {
|
||||
|
||||
//MARK:-Functions to subclass
|
||||
// Subclass for a top view.
|
||||
public func viewForTop() -> UIView? {
|
||||
open func viewForTop() -> UIView? {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Subclass for a middle view.
|
||||
public func viewForMiddle() -> UIView? {
|
||||
open func viewForMiddle() -> UIView? {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Subclass for a bottom view.
|
||||
public func viewForBottom() -> UIView? {
|
||||
open func viewForBottom() -> UIView? {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If a value is set, the middle view is pinned this value below the top view, if not, space is left to fill.
|
||||
public func spaceBetweenTopAndMiddle() -> CGFloat? {
|
||||
open func spaceBetweenTopAndMiddle() -> CGFloat? {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If a value is set, the middle view is pinned this value above the bottom view, if not, space is left to fill.
|
||||
public func spaceBetweenMiddleAndBottom() -> CGFloat? {
|
||||
open func spaceBetweenMiddleAndBottom() -> CGFloat? {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -246,7 +246,7 @@ extension ThreeLayerViewController {
|
||||
|
||||
//MARK:-Animation
|
||||
extension ThreeLayerViewController {
|
||||
public override func setupIntroAnimations() {
|
||||
open override func setupIntroAnimations() {
|
||||
if let topView = topView, topView.subviews.count > 0 {
|
||||
introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: topView))
|
||||
}
|
||||
|
||||
27
MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift
Normal file
27
MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// FormValidationProtocol.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 3/26/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc public protocol FormValidationProtocol: NSObjectProtocol {
|
||||
|
||||
// Getter method to get the FormValidator form the delegate (Mostly from the parent View Controller)
|
||||
@objc optional func formValidatorModel() -> FormValidator?
|
||||
|
||||
// Used to check the validity of the field, to enable/disable the primary button.
|
||||
@objc optional func isValidField() -> Bool
|
||||
|
||||
// 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 Feild value key value paid for sending to server
|
||||
@objc optional func formFieldValue() -> String?
|
||||
}
|
||||
31
MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift
Normal file
31
MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift
Normal file
@ -0,0 +1,31 @@
|
||||
//
|
||||
// MVMCoreUIFormValidator+FormParams.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 3/21/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc public extension FormValidator {
|
||||
@objc public func addFormParams(requestParameters: MVMCoreRequestParameters) {
|
||||
requestParameters.add(self.getFormParams())
|
||||
}
|
||||
|
||||
@objc public 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,
|
||||
let fieldName = formFieldName(),
|
||||
let fieldValue = formFieldValue() {
|
||||
|
||||
extraParam[fieldName] = fieldValue
|
||||
}
|
||||
}
|
||||
})
|
||||
return extraParam
|
||||
}
|
||||
}
|
||||
92
MVMCoreUI/FormUIHelpers/FormValidator+TextFields.swift
Normal file
92
MVMCoreUI/FormUIHelpers/FormValidator+TextFields.swift
Normal file
@ -0,0 +1,92 @@
|
||||
//
|
||||
// MVMCoreUIFormValidator+TextFields.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 3/21/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc extension FormValidator: UITextFieldDelegate {
|
||||
public func textFieldDidEndEditing(_ textField: UITextField) {
|
||||
enableByValidation()
|
||||
if let delegate = delegate as? UITextFieldDelegate {
|
||||
delegate.textFieldDidEndEditing?(textField)
|
||||
}
|
||||
}
|
||||
|
||||
public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||
textField.resignFirstResponder()
|
||||
if let delegate = delegate as? UITextFieldDelegate {
|
||||
return delegate.textFieldShouldReturn?(textField) ?? true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
public func textFieldDidBeginEditing(_ textField: UITextField) {
|
||||
if let delegate = delegate as? UITextFieldDelegate {
|
||||
delegate.textFieldDidBeginEditing?(textField)
|
||||
}
|
||||
}
|
||||
|
||||
public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
|
||||
if let delegate = delegate as? UITextFieldDelegate {
|
||||
return delegate.textFieldShouldBeginEditing?(textField) ?? true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
public func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
|
||||
if let delegate = delegate as? UITextFieldDelegate {
|
||||
return delegate.textFieldShouldEndEditing?(textField) ?? true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
public func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) {
|
||||
if let delegate = delegate as? UITextFieldDelegate {
|
||||
delegate.textFieldDidEndEditing?(textField, reason: reason)
|
||||
}
|
||||
}
|
||||
|
||||
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||
if let delegate = delegate as? UITextFieldDelegate {
|
||||
return delegate.textField?(textField, shouldChangeCharactersIn: range, replacementString: string) ?? true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
public func textFieldShouldClear(_ textField: UITextField) -> Bool {
|
||||
if let delegate = delegate as? UITextFieldDelegate {
|
||||
return delegate.textFieldShouldClear?(textField) ?? true
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@objc extension FormValidator: MFTextFieldDelegate {
|
||||
public func dismissFieldInput(_ sender: Any?) {
|
||||
if let delegate = delegate as? MFTextFieldDelegate {
|
||||
delegate.dismissFieldInput?(sender)
|
||||
}
|
||||
}
|
||||
|
||||
public func entryIsValid(_ textfield: MFTextField?) {
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||
self.enableByValidation()
|
||||
if let delegate = self.delegate as? MFTextFieldDelegate {
|
||||
delegate.entryIsValid?(textfield)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public func entryIsInvalid(_ textfield: MFTextField?) {
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||
self.enableByValidation()
|
||||
if let delegate = self.delegate as? MFTextFieldDelegate {
|
||||
delegate.entryIsInvalid?(textfield)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
59
MVMCoreUI/FormUIHelpers/FormValidator.swift
Normal file
59
MVMCoreUI/FormUIHelpers/FormValidator.swift
Normal file
@ -0,0 +1,59 @@
|
||||
//
|
||||
// FormValidator.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 3/26/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
@objcMembers public class FormValidator: NSObject {
|
||||
|
||||
var delegate: FormValidationProtocol?
|
||||
var molecules: [UIView & FormValidationProtocol] = []
|
||||
var extraValidationBlock: (() -> Bool)?
|
||||
|
||||
public func insertMolecule(_ molecule: UIView & FormValidationProtocol) {
|
||||
molecules.append(molecule)
|
||||
}
|
||||
|
||||
public static func getFormValidatorFor(delegate: FormValidationProtocol) -> FormValidator? {
|
||||
if let delegateFormValidatorModel = delegate.formValidatorModel,
|
||||
let validator = delegateFormValidatorModel() {
|
||||
return validator
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public static func setupValidation(molecule: UIView & FormValidationProtocol, delegate: FormValidationProtocol?) {
|
||||
if let delegateFormValidatorModel = delegate?.formValidatorModel,
|
||||
let validator = delegateFormValidatorModel() {
|
||||
|
||||
validator.delegate = delegate
|
||||
validator.insertMolecule(molecule)
|
||||
}
|
||||
}
|
||||
|
||||
public func enableByValidation() {
|
||||
var valid = true
|
||||
for molecule in molecules {
|
||||
if let isValidField = molecule.isValidField,
|
||||
isValidField() == false {
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
let enableField = valid && (extraValidationBlock?() ?? true)
|
||||
shouldEnable(enableField)
|
||||
}
|
||||
|
||||
public func shouldEnable(_ enable: Bool) {
|
||||
for molecule in molecules {
|
||||
if let enableField = molecule.enableField {
|
||||
enableField(enable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,7 +10,7 @@ import UIKit
|
||||
import MVMCore
|
||||
|
||||
|
||||
public class MFTextFieldListView: MFView {
|
||||
public class MFTextFieldListView: ViewConstrainingView {
|
||||
|
||||
public var textFieldMapList: [[String: Any]]?
|
||||
public var parentViewContoller: MFViewController?
|
||||
@ -24,7 +24,7 @@ public class MFTextFieldListView: MFView {
|
||||
self.primaryButton = primaryButton
|
||||
super.init(frame: .zero)
|
||||
}
|
||||
|
||||
|
||||
public required init?(coder decoder: NSCoder) {
|
||||
super.init(coder: decoder)
|
||||
}
|
||||
|
||||
@ -16,17 +16,17 @@ public class MoleculeStackView: MFView {
|
||||
super.init(frame: frame)
|
||||
}
|
||||
|
||||
init(withJSON json: [AnyHashable : Any]?, delegate: NSObject?, additionalData: [AnyHashable : Any]?) {
|
||||
public init(withJSON json: [AnyHashable : Any]?, delegate: NSObject?, additionalData: [AnyHashable : Any]?) {
|
||||
super.init(frame: CGRect.zero)
|
||||
setWithJSON(json, delegate: delegate, additionalData: additionalData)
|
||||
}
|
||||
|
||||
convenience init(withJSON json: [AnyHashable : Any]?, delegate: NSObject?, spacingBlock: ((Any) -> UIEdgeInsets)?) {
|
||||
public convenience init(withJSON json: [AnyHashable : Any]?, delegate: NSObject?, spacingBlock: ((Any) -> UIEdgeInsets)?) {
|
||||
self.init(withJSON: json, delegate: delegate, additionalData: nil)
|
||||
self.spacingBlock = spacingBlock
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
@import MVMCore.NSDictionary_MFConvenience;
|
||||
#import "MVMCoreUIObject.h"
|
||||
#import <MVMCoreUI/MVMCoreUI-Swift.h>
|
||||
#import "MFTextField.h"
|
||||
|
||||
@implementation MVMCoreUIMoleculeMappingObject
|
||||
|
||||
@ -30,7 +31,8 @@
|
||||
@"twoButtonView": TwoButtonView.class,
|
||||
@"standardFooter": StandardFooterView.class,
|
||||
@"caretView": CaretView.class,
|
||||
@"caretButton": CaretButton.class
|
||||
@"caretButton": CaretButton.class,
|
||||
@"textField" : MFTextField.class
|
||||
} mutableCopy];
|
||||
});
|
||||
return mapping;
|
||||
@ -59,8 +61,9 @@
|
||||
return nil;
|
||||
}
|
||||
UIView <MVMCoreUIMoleculeViewProtocol>*molecule = [self getMoleculeForName:moleculeName];
|
||||
[molecule setWithJSON:json delegate:delegate additionalData:nil];
|
||||
[molecule setWithJSON:json delegate:delegate additionalData:nil];
|
||||
return molecule;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@ -17,14 +17,16 @@ public class MoleculeStackCenteredTemplate: ThreeLayerViewController {
|
||||
}
|
||||
|
||||
public override func viewForTop() -> UIView? {
|
||||
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegate: self) else {
|
||||
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"),
|
||||
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegate: self) else {
|
||||
return nil
|
||||
}
|
||||
return molecule
|
||||
}
|
||||
|
||||
override public func viewForBottom() -> UIView? {
|
||||
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegate: self) else {
|
||||
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"),
|
||||
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegate: self) else {
|
||||
return nil
|
||||
}
|
||||
return molecule
|
||||
|
||||
Loading…
Reference in New Issue
Block a user