Skip to content

Commit bf7780c

Browse files
committed
Add required field validation property
1 parent 6db8649 commit bf7780c

File tree

3 files changed

+39
-7
lines changed

3 files changed

+39
-7
lines changed

Example/FloatingLabelTextFieldSwiftUI/ContentView.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ struct ContentView: View {
5050
.addValidations([.init(condition: firstName.isValid(.alphabet), errorMessage: "Invalid Name"),
5151
.init(condition: firstName.count >= 2, errorMessage: "Minimum two character long")
5252
])
53+
.isRequiredField(true, with: "Name field is required")
5354
.floatingStyle(ThemeTextFieldStyle())
5455
.modifier(ThemeTextField())
5556

@@ -102,6 +103,8 @@ struct ContentView: View {
102103
}) {
103104

104105
}
106+
.isShowError(true)
107+
.isRequiredField(true, with: "Password field is required")
105108
.rightView({
106109
Button(action: {
107110
withAnimation {

Sources/FloatingLabelTextFieldSwiftUI/FloatingLabelTextField.swift

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,20 @@ public struct FloatingLabelTextField: View {
2222
@Binding private var textFieldValue: String
2323
@State fileprivate var isSelected: Bool = false
2424
@Binding private var validtionChecker: Bool
25+
2526
private var currentError: TextFieldValidator {
27+
if notifier.isRequiredField && isShowError && textFieldValue.isEmpty {
28+
return TextFieldValidator(condition: false, errorMessage: notifier.requiredFieldMessage)
29+
}
30+
2631
if let firstError = notifier.arrValidator.filter({!$0.condition}).first {
2732
return firstError
2833
}
2934
return TextFieldValidator(condition: true, errorMessage: "")
3035
}
3136

37+
@State fileprivate var isShowError: Bool = false
38+
3239
//MARK: Observed Object
3340
@ObservedObject private var notifier = FloatingLabelTextFieldNotifier()
3441

@@ -61,6 +68,7 @@ public struct FloatingLabelTextField: View {
6168
SecureField("", text: $textFieldValue.animation()) {
6269
}
6370
.onTapGesture {
71+
self.isShowError = self.notifier.isRequiredField
6472
self.validtionChecker = self.currentError.condition
6573
self.editingChanged(self.isSelected)
6674
if !self.isSelected {
@@ -71,6 +79,7 @@ public struct FloatingLabelTextField: View {
7179
self.isSelected = self.notifier.isSecureTextEntry
7280
currentTextField.addAction(for: .editingDidEnd) {
7381
self.isSelected = false
82+
self.isShowError = self.notifier.isRequiredField
7483
self.commit()
7584
}
7685
}
@@ -85,8 +94,10 @@ public struct FloatingLabelTextField: View {
8594
self.isSelected = isChanged
8695
self.validtionChecker = self.currentError.condition
8796
self.editingChanged(isChanged)
97+
self.isShowError = self.notifier.isRequiredField
8898

8999
}, onCommit: {
100+
self.isShowError = self.notifier.isRequiredField
90101
self.validtionChecker = self.currentError.condition
91102
self.commit()
92103
})
@@ -97,6 +108,15 @@ public struct FloatingLabelTextField: View {
97108
}
98109
}
99110

111+
// MARK: Top error and title lable view
112+
var topTitleLable: some View {
113+
Text((self.currentError.condition || !notifier.isShowError) ? placeholderText : self.currentError.errorMessage)
114+
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: notifier.textAlignment.getAlignment())
115+
.animation(.default)
116+
.foregroundColor((self.currentError.condition || !notifier.isShowError) ? (self.isSelected ? notifier.selectedTitleColor : notifier.titleColor) : notifier.errorColor)
117+
.font(notifier.titleFont)
118+
}
119+
100120
// MARK: Bottom Line View
101121
var bottomLine: some View {
102122
Divider()
@@ -108,13 +128,13 @@ public struct FloatingLabelTextField: View {
108128
VStack () {
109129
ZStack(alignment: .bottomLeading) {
110130

111-
Text((self.currentError.condition || !notifier.isShowError) ? placeholderText : self.currentError.errorMessage)
112-
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: notifier.textAlignment.getAlignment())
113-
.animation(.default)
114-
.foregroundColor((self.currentError.condition || !notifier.isShowError) ? (self.isSelected ? notifier.selectedTitleColor : notifier.titleColor) : notifier.errorColor)
115-
.padding(.bottom, CGFloat(!textFieldValue.isEmpty ? notifier.spaceBetweenTitleText : 0))
116-
.opacity(textFieldValue.isEmpty ? 0 : 1)
117-
.font(notifier.titleFont)
131+
//Top error and title lable view
132+
if notifier.isShowError && self.isShowError && textFieldValue.isEmpty {
133+
self.topTitleLable.padding(.bottom, CGFloat(notifier.spaceBetweenTitleText)).opacity(1)
134+
135+
} else {
136+
self.topTitleLable.padding(.bottom, CGFloat(!textFieldValue.isEmpty ? notifier.spaceBetweenTitleText : 0)).opacity((textFieldValue.isEmpty) ? 0 : 1)
137+
}
118138

119139
HStack {
120140
// Left View
@@ -303,6 +323,13 @@ extension FloatingLabelTextField {
303323
notifier.errorColor = color
304324
return self
305325
}
326+
327+
/// Sets the field is required or not with message.
328+
public func isRequiredField(_ required: Bool, with message: String) -> Self {
329+
notifier.isRequiredField = required
330+
notifier.requiredFieldMessage = message
331+
return self
332+
}
306333
}
307334

308335
//MARK: Preview

Sources/FloatingLabelTextFieldSwiftUI/ObservableObject/ObservableObject.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,6 @@ class FloatingLabelTextFieldNotifier: ObservableObject {
4646
@Published var isShowError: Bool = false
4747
@Published var errorColor: Color = .red
4848
@Published var arrValidator: [TextFieldValidator] = []
49+
@Published var isRequiredField: Bool = false
50+
@Published var requiredFieldMessage: String = ""
4951
}

0 commit comments

Comments
 (0)