@@ -18,6 +18,19 @@ public class FormControl<FieldName> where FieldName: Hashable {
1818 private( set) public var formState : FormState < FieldName >
1919 var instantFormState : FormState < FieldName >
2020
21+ var _currentFocusedField : FieldName ?
22+ var currentFocusedField : FieldName ? {
23+ get {
24+ _currentFocusedField ?? options. focusedFieldOption. focusedFieldBindingValue
25+ }
26+ set {
27+ if options. focusedFieldOption. hasFocusedFieldBinder {
28+ return
29+ }
30+ _currentFocusedField = newValue
31+ }
32+ }
33+
2134 init ( options: FormOption < FieldName > , formState: Binding < FormState < FieldName > > ) {
2235 self . options = options
2336 self . fields = [ : ]
@@ -34,8 +47,11 @@ public class FormControl<FieldName> where FieldName: Hashable {
3447 instantFormState. formValues [ name] = options. defaultValue
3548 }
3649 field. options = options
50+ if let fieldOrdinal = options. fieldOrdinal {
51+ field. fieldOrdinal = fieldOrdinal
52+ }
3753 } else {
38- field = Field ( index : fields. count, name: name, options: options, control: self )
54+ field = Field ( fieldOrdinal : options . fieldOrdinal ?? fields. count, name: name, options: options, control: self )
3955 fields [ name] = field
4056 instantFormState. formValues [ name] = options. defaultValue
4157 }
@@ -98,7 +114,7 @@ public class FormControl<FieldName> where FieldName: Hashable {
98114 case . success( let formValues) :
99115 isOveralValid = true
100116 errors = . init( )
101- instantFormState. formValues. update ( other : formValues)
117+ instantFormState. formValues. unioned ( formValues)
102118 case . failure( let e) :
103119 isOveralValid = false
104120 errors = e
@@ -138,7 +154,7 @@ public class FormControl<FieldName> where FieldName: Hashable {
138154 case . success( let formValues) :
139155 isOveralValid = true
140156 errors = . init( )
141- instantFormState. formValues. update ( other : formValues)
157+ instantFormState. formValues. unioned ( formValues)
142158 case . failure( let e) :
143159 isOveralValid = false
144160 errors = e
@@ -176,25 +192,37 @@ public class FormControl<FieldName> where FieldName: Hashable {
176192 try await onValid ( instantFormState. formValues, errors)
177193 } else if let onInvalid {
178194 try await onInvalid ( instantFormState. formValues, errors)
179- await focusError ( with: errors)
180195 }
181196 await postHandleSubmit ( isOveralValid: isOveralValid, errors: errors, isSubmitSuccessful: errors. errorFields. isEmpty)
197+ if !isOveralValid {
198+ await focusError ( with: errors)
199+ }
182200 } catch {
183201 await postHandleSubmit ( isOveralValid: isOveralValid, errors: errors, isSubmitSuccessful: false )
184202 throw error
185203 }
186204 }
187205
188- private func focusError( with errors: FormError < FieldName > ) async {
206+ @MainActor
207+ private func focusError( with errors: FormError < FieldName > ) {
189208 guard options. shouldFocusError else {
190209 return
191210 }
192- let fields = fields
193- . sorted { $0. value. index < $1. value. index }
194- guard let firstErrorField = fields. first ( where: { errors. errorFields. contains ( $0. key) } ) ? . key else {
211+ let fields = fields. sorted { $0. value. fieldOrdinal < $1. value. fieldOrdinal }
212+ let firstErrorField = fields. first ( where: { errors. errorFields. contains ( $0. key) } ) ? . key
213+ guard let firstErrorField else {
214+ return
215+ }
216+ currentFocusedField = firstErrorField
217+ options. focusedFieldOption. triggerFocus ( on: firstErrorField)
218+ }
219+
220+ @MainActor
221+ private func focusOnCurrentField( ) {
222+ guard let currentFocusedField else {
195223 return
196224 }
197- await options. focusedFieldOption. triggerFocus ( on: firstErrorField )
225+ options. focusedFieldOption. triggerFocus ( on: currentFocusedField )
198226 }
199227
200228 private func postHandleSubmit( isOveralValid: Bool , errors: FormError < FieldName > , isSubmitSuccessful: Bool ) async {
@@ -214,6 +242,7 @@ public class FormControl<FieldName> where FieldName: Hashable {
214242 try await Task . sleep ( nanoseconds: delayErrorInNanoseconds)
215243 self ? . instantFormState. errors = errors
216244 await self ? . syncFormState ( )
245+ await self ? . focusOnCurrentField ( )
217246 }
218247 }
219248 }
@@ -301,7 +330,7 @@ public class FormControl<FieldName> where FieldName: Hashable {
301330 case . success:
302331 break
303332 case . failure( let e) :
304- instantFormState. errors = instantFormState. errors. rewrite ( from : e)
333+ instantFormState. errors = instantFormState. errors. union ( e)
305334 instantFormState. isValid = false
306335 }
307336 } else if let field = fields [ name] {
@@ -335,10 +364,10 @@ public class FormControl<FieldName> where FieldName: Hashable {
335364 case . success( let formValues) :
336365 isValid = true
337366 errors = instantFormState. errors
338- instantFormState. formValues. update ( other : formValues)
367+ instantFormState. formValues. unioned ( formValues)
339368 case . failure( let e) :
340369 isValid = false
341- errors = instantFormState. errors. rewrite ( from : e)
370+ errors = instantFormState. errors. union ( e)
342371 }
343372 } else {
344373 ( isValid, errors) = await withTaskGroup ( of: KeyValidationResult . self) { group in
@@ -377,6 +406,7 @@ public class FormControl<FieldName> where FieldName: Hashable {
377406 try await Task . sleep ( nanoseconds: delayErrorInNanoseconds)
378407 self ? . instantFormState. errors = errors
379408 await self ? . syncFormState ( )
409+ await self ? . focusOnCurrentField ( )
380410 }
381411 }
382412 return isValid
@@ -399,7 +429,7 @@ extension FormControl {
399429 switch result {
400430 case . success( let formValues) :
401431 isValid = true
402- instantFormState. formValues. update ( other : formValues)
432+ instantFormState. formValues. unioned ( formValues)
403433 case . failure( let e) :
404434 isValid = false
405435 currentErrorNotifyTask? . cancel ( )
@@ -412,6 +442,7 @@ extension FormControl {
412442 try await Task . sleep ( nanoseconds: delayErrorInNanoseconds)
413443 self ? . instantFormState. errors = e
414444 await self ? . syncFormState ( )
445+ await self ? . focusOnCurrentField ( )
415446 }
416447 }
417448 }
@@ -445,6 +476,7 @@ extension FormControl {
445476 try await Task . sleep ( nanoseconds: delayErrorInNanoseconds)
446477 self ? . instantFormState. errors = errors
447478 await self ? . syncFormState ( )
479+ await self ? . focusOnCurrentField ( )
448480 }
449481 }
450482 instantFormState. isValid = isValid
@@ -463,7 +495,7 @@ extension FormControl {
463495
464496private extension FormControl {
465497 class Field < Value> : FieldProtocol {
466- let index : Int
498+ var fieldOrdinal : Int
467499 let name : FieldName
468500 var options : RegisterOption < Value > {
469501 didSet {
@@ -476,8 +508,8 @@ private extension FormControl {
476508 unowned var control : FormControl < FieldName >
477509 var value : Binding < Value >
478510
479- init ( index : Int , name: FieldName , options: RegisterOption < Value > , control: FormControl < FieldName > ) {
480- self . index = index
511+ init ( fieldOrdinal : Int , name: FieldName , options: RegisterOption < Value > , control: FormControl < FieldName > ) {
512+ self . fieldOrdinal = fieldOrdinal
481513 self . name = name
482514 self . options = options
483515 self . control = control
@@ -501,7 +533,7 @@ private extension FormControl {
501533 . init { [ weak self] in
502534 self ? . instantFormState. formValues [ name] as? Value ?? defaultValue
503535 } set: { [ weak self] value in
504- guard let self = self else {
536+ guard let self else {
505537 return
506538 }
507539 self . instantFormState. formValues [ name] = value
@@ -512,8 +544,16 @@ private extension FormControl {
512544 return
513545 }
514546 Task {
515- await self . trigger ( name: name)
516- await self . options. focusedFieldOption. triggerFocus ( on: name)
547+ guard await self . trigger ( name: name) else {
548+ return
549+ }
550+ await MainActor . run {
551+ if self . currentFocusedField == name {
552+ return
553+ }
554+ self . currentFocusedField = name
555+ self . options. focusedFieldOption. triggerFocus ( on: name)
556+ }
517557 }
518558 }
519559 }
0 commit comments