First cut at form fiedable change
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
parent
05638422f6
commit
69a2374504
@ -31,7 +31,7 @@ extension LabelAttributeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func isValidRange(on attributedString: NSMutableAttributedString) -> Bool {
|
public func isValidRange(on attributedString: NSMutableAttributedString) -> Bool {
|
||||||
true//range.location + range.length <= attributedString.string.count
|
range.location + range.length <= attributedString.string.count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import Combine
|
|||||||
|
|
||||||
/// Base Class used to build out a Input controls.
|
/// Base Class used to build out a Input controls.
|
||||||
@objc(VDSEntryField)
|
@objc(VDSEntryField)
|
||||||
open class EntryFieldBase: Control, Changeable {
|
open class EntryFieldBase: Control, Changeable, FormFieldable {
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializers
|
// MARK: - Initializers
|
||||||
@ -196,7 +196,7 @@ open class EntryFieldBase: Control, Changeable {
|
|||||||
|
|
||||||
open var inputId: String? { didSet { setNeedsUpdate() } }
|
open var inputId: String? { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
open var value: AnyHashable? { didSet { setNeedsUpdate() } }
|
open var value: String? { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
open var defaultValue: AnyHashable? { didSet { setNeedsUpdate() } }
|
open var defaultValue: AnyHashable? { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
|
|||||||
@ -79,13 +79,13 @@ open class InputField: EntryFieldBase, UITextFieldDelegate {
|
|||||||
open var fieldType: FieldType = .text { didSet { setNeedsUpdate() } }
|
open var fieldType: FieldType = .text { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
/// The text of this textField.
|
/// The text of this textField.
|
||||||
open override var text: String? {
|
open override var value: String? {
|
||||||
get { textField.text }
|
get { textField.text }
|
||||||
set {
|
set {
|
||||||
textField.text = newValue
|
textField.text = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var _showError: Bool = false
|
var _showError: Bool = false
|
||||||
/// Whether not to show the error.
|
/// Whether not to show the error.
|
||||||
open override var showError: Bool {
|
open override var showError: Bool {
|
||||||
|
|||||||
@ -107,14 +107,15 @@ open class TextArea: EntryFieldBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The text of this textField.
|
open override var value: String? {
|
||||||
open override var text: String? {
|
|
||||||
get { textView.text }
|
get { textView.text }
|
||||||
set {
|
set {
|
||||||
textView.text = newValue
|
textView.text = newValue
|
||||||
|
setNeedsUpdate()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// UITextView shown in the TextArea.
|
/// UITextView shown in the TextArea.
|
||||||
open var textView = TextView().with {
|
open var textView = TextView().with {
|
||||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||||
@ -184,7 +185,7 @@ open class TextArea: EntryFieldBase {
|
|||||||
/// Used to make changes to the View based off a change events or from local properties.
|
/// Used to make changes to the View based off a change events or from local properties.
|
||||||
open override func updateView() {
|
open override func updateView() {
|
||||||
super.updateView()
|
super.updateView()
|
||||||
|
countRule.maxLength = maxLength
|
||||||
textView.isEditable = isEnabled
|
textView.isEditable = isEnabled
|
||||||
textView.isEnabled = isEnabled
|
textView.isEnabled = isEnabled
|
||||||
textView.surface = surface
|
textView.surface = surface
|
||||||
@ -208,6 +209,9 @@ open class TextArea: EntryFieldBase {
|
|||||||
} else {
|
} else {
|
||||||
characterCounterLabel.text = ""
|
characterCounterLabel.text = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showError = !validator.validate()
|
||||||
|
errorText = validator.errorMessage
|
||||||
|
|
||||||
icon.size = .medium
|
icon.size = .medium
|
||||||
icon.color = iconColorConfiguration.getColor(self)
|
icon.color = iconColorConfiguration.getColor(self)
|
||||||
@ -246,12 +250,8 @@ open class TextArea: EntryFieldBase {
|
|||||||
let countStr = (count > maxLength ?? 0) ? ("-" + "\(count-(maxLength ?? 0))") : "\(count)"
|
let countStr = (count > maxLength ?? 0) ? ("-" + "\(count-(maxLength ?? 0))") : "\(count)"
|
||||||
if ((maxLength ?? 0) > 0) {
|
if ((maxLength ?? 0) > 0) {
|
||||||
if (count > (maxLength ?? 0)) {
|
if (count > (maxLength ?? 0)) {
|
||||||
showError = true
|
|
||||||
errorText = "You have exceeded the character limit."
|
|
||||||
return countStr
|
return countStr
|
||||||
} else {
|
} else {
|
||||||
showError = false
|
|
||||||
errorText = ""
|
|
||||||
return ("\(countStr)" + "/" + "\(maxLength ?? 0)")
|
return ("\(countStr)" + "/" + "\(maxLength ?? 0)")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -274,6 +274,33 @@ open class TextArea: EntryFieldBase {
|
|||||||
|
|
||||||
textView.textAttributes = textAttributes
|
textView.textAttributes = textAttributes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Validation
|
||||||
|
//--------------------------------------------------
|
||||||
|
var countRule = CharacterCountRule()
|
||||||
|
lazy var validator: FieldValidator<TextArea> = {
|
||||||
|
let validator = FieldValidator<TextArea>(field: self, rules: [.init(countRule)])
|
||||||
|
return validator
|
||||||
|
}()
|
||||||
|
|
||||||
|
class CharacterCountRule: Rule {
|
||||||
|
var maxLength: Int?
|
||||||
|
var errorMessage: String = "You have exceeded the character limit."
|
||||||
|
|
||||||
|
func isValid(value: String?) -> Bool {
|
||||||
|
guard let text = value else { return true }
|
||||||
|
|
||||||
|
if ((maxLength ?? 0) > 0) {
|
||||||
|
if (text.count > (maxLength ?? 0)) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TextArea: UITextViewDelegate {
|
extension TextArea: UITextViewDelegate {
|
||||||
|
|||||||
@ -9,10 +9,66 @@ import Foundation
|
|||||||
|
|
||||||
/// Protocol used for a FormField object.
|
/// Protocol used for a FormField object.
|
||||||
public protocol FormFieldable {
|
public protocol FormFieldable {
|
||||||
|
associatedtype ValueType = AnyHashable
|
||||||
|
|
||||||
/// Unique Id for the Form Field object within a Form.
|
/// Unique Id for the Form Field object within a Form.
|
||||||
var inputId: String? { get set }
|
var inputId: String? { get set }
|
||||||
|
|
||||||
/// Value for the Form Field.
|
/// Value for the Form Field.
|
||||||
var value: AnyHashable? { get set }
|
var value: ValueType? { get set }
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct AnyRule<ValueType> {
|
||||||
|
private let _isValid: (ValueType?) -> Bool
|
||||||
|
public let errorMessage: String
|
||||||
|
|
||||||
|
init<R: Rule>(_ rule: R) where R.ValueType == ValueType {
|
||||||
|
self._isValid = rule.isValid
|
||||||
|
self.errorMessage = rule.errorMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
public func isValid(value: Any?) -> Bool {
|
||||||
|
guard let typedValue = value as? ValueType? else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return _isValid(typedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol Rule<ValueType> {
|
||||||
|
associatedtype ValueType
|
||||||
|
func isValid(value: ValueType?) -> Bool
|
||||||
|
var errorMessage: String { get }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FieldValidator<Field:FormFieldable>{
|
||||||
|
public var field: Field
|
||||||
|
public var rules: [AnyRule<Field.ValueType>]?
|
||||||
|
public var errorMessages = [String]()
|
||||||
|
|
||||||
|
public init(field: Field, rules: [AnyRule<Field.ValueType>]? = nil) {
|
||||||
|
self.field = field
|
||||||
|
self.rules = rules
|
||||||
|
}
|
||||||
|
|
||||||
|
public var errorMessage: String? {
|
||||||
|
errorMessages.joined(separator: "\r")
|
||||||
|
}
|
||||||
|
|
||||||
|
public func validate() -> Bool{
|
||||||
|
errorMessages.removeAll()
|
||||||
|
|
||||||
|
guard let rules else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for rule in rules {
|
||||||
|
if !rule.isValid(value: field.value) {
|
||||||
|
errorMessages.append(rule.errorMessage)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user