@@ -88,7 +88,7 @@ class OudsPhoneNumberInput extends StatefulWidget {
8888 final TextInputType ? keyboardType;
8989 CountrySelector ? countrySelector;
9090 final OudsInputDecoration decoration;
91- final void Function (String )? onCompleted ;
91+ final void Function (String )? onEditingComplete ;
9292
9393 OudsPhoneNumberInput ({
9494 super .key,
@@ -99,7 +99,7 @@ class OudsPhoneNumberInput extends StatefulWidget {
9999 this .keyboardType,
100100 this .countrySelector,
101101 required this .decoration,
102- this .onCompleted ,
102+ this .onEditingComplete ,
103103 }) : assert (
104104 ! (decoration.loader == true && decoration.errorText != null ),
105105 "Error status for Loading state is not relevant" ,
@@ -280,74 +280,22 @@ class _OudsPhoneNumberInputState extends State<OudsPhoneNumberInput> {
280280 readOnly: widget.readOnly ?? false ,
281281 onTap: () {
282282 // send text tapped to parent
283- widget.onCompleted ? .call (widget.controller? .text ?? '' );
283+ widget.onEditingComplete ? .call (widget.controller? .text ?? '' );
284284 },
285285 onTapOutside: (outside) {
286286 // send text tapped to parent
287- widget.onCompleted ? .call (widget.controller? .text ?? '' );
287+ widget.onEditingComplete ? .call (widget.controller? .text ?? '' );
288288 },
289289 onEditingComplete: () {
290290 // send text tapped to parent
291- widget.onCompleted ? .call (widget.controller? .text ?? '' );
291+ widget.onEditingComplete ? .call (widget.controller? .text ?? '' );
292292 },
293293 onSubmitted: (value) {
294294 // send text tapped to parent
295- widget.onCompleted ? .call (value);
295+ widget.onEditingComplete ? .call (value);
296296 },
297297 onChanged: (value) {
298- // Select a Country if prefix of decoration is add
299- // if we take the prefix from current local or country selected
300- if (widget.decoration.prefix != null ) {
301- countrySelected = CountryService ().findCountryByPrefix (widget.decoration.prefix! ) ?? Country .empty ();
302- } else {
303- countrySelected = widget.countrySelector? .selectedCountry ?? Country .empty ();
304- }
305- // Clean the input to keep only digits
306- final digitsOnly = value.replaceAll (RegExp (r'\D' ), '' );
307-
308- // Retrieve the maximum allowed length for the selected country
309- maxLength = getMaxDigitsFromLib (countrySelected.code);
310- // Store the maximum length for future reference
311- //maxLength = maxDigits;
312-
313- // Limit the input to the maximum length
314- limitedDigits = digitsOnly;
315- if (maxLength != null && digitsOnly.length > maxLength! ) {
316- limitedDigits = digitsOnly.substring (0 , maxLength);
317- }
318-
319- // Format the number
320- try {
321- if (widget.countrySelector == null ) {
322- // Parse and format as national number if country selector is disabled
323- final parsedNumber = phoneUtil.parse (limitedDigits, countrySelected.code.toUpperCase ());
324- formattedNumber = phoneUtil.format (parsedNumber, PhoneNumberFormat .national);
325- } else {
326- // Parse and format as international number if country selector is enabled
327- final parsedNumber = phoneUtil.parse (limitedDigits, countrySelected.code.toUpperCase ());
328- String phoneNumber = phoneUtil.format (parsedNumber, PhoneNumberFormat .international);
329- // Convert international number to national format
330- formattedNumber = getNationalNumber (phoneNumber, countrySelected.code.toUpperCase ());
331- }
332-
333- // Update the controller's value with the formatted number
334- final selectionIndex = widget.controller? .selection.baseOffset ?? 0 ;
335-
336- widget.controller? .value = TextEditingValue (
337- text: formattedNumber! ,
338- // Keep the cursor position after the inserted formatted number
339- selection: TextSelection .collapsed (offset: selectionIndex + (formattedNumber! .length)),
340- );
341-
342- debugPrint ("maxLength: $maxLength , limitedDigits: $limitedDigits , formattedNumber: $formattedNumber , value: $value , country: ${countrySelected .code .toUpperCase ()}" );
343- } catch (e) {
344- // If an error occurs during parsing or formatting, keep the raw digits
345- widget.controller? .value = TextEditingValue (
346- text: limitedDigits,
347- // Place cursor at the end of the input
348- selection: TextSelection .collapsed (offset: limitedDigits.length),
349- );
350- }
298+ _onCountryChanged (value, limitedDigits, formattedNumber);
351299 },
352300 decoration: InputDecoration (
353301 border: InputBorder .none,
@@ -363,13 +311,7 @@ class _OudsPhoneNumberInputState extends State<OudsPhoneNumberInput> {
363311 : null ,
364312
365313 // Floating label behavior: always float if both labelText and hintText are provided
366- floatingLabelBehavior: ! effectiveIsFocused
367- ? (widget.decoration.labelText != null && widget.decoration.hintText != null )
368- ? FloatingLabelBehavior .never
369- : null
370- : (widget.decoration.labelText != null && widget.decoration.hintText != null )
371- ? FloatingLabelBehavior .always
372- : null ,
314+ floatingLabelBehavior: (widget.decoration.labelText != null && widget.decoration.hintText != null ) ? FloatingLabelBehavior .always : null ,
373315
374316 // Hint text widget, shown if hintText is provided
375317 hint: formattedNumber.isNotEmpty || widget.decoration.hintText != null
@@ -411,6 +353,78 @@ class _OudsPhoneNumberInputState extends State<OudsPhoneNumberInput> {
411353 );
412354 }
413355
356+ /// Function `_onCountryChanged`
357+ ///
358+ /// This function is triggered when the selected country or phone number changes.
359+ /// It updates the phone number formatting based on the selected country,
360+ /// limits the number length according to the country, and updates the text controller.
361+ ///
362+ /// Parameters :
363+ /// - `value` : The new input value of the phone number entered by the user.
364+ /// - `limitedDigits` : The string containing only digits of the number, limited to the maximum length.
365+ /// - `formattedNumber` : The formatted version of the phone number, which will be updated in the controller.
366+ ///
367+ /// Behavior :
368+ /// - Determines the selected country based on the prefix or current selection.
369+ /// - Cleans the number to keep only digits.
370+ /// - Limits the number length based on the country configuration.
371+ /// - Formats the number in national or international format depending on the configuration.
372+ /// - Updates the text controller with the formatted number, maintaining the cursor position.
373+ /// - If an error occurs during parsing or formatting, retains the raw digit version.
374+ void _onCountryChanged (String value, String limitedDigits, String ? formattedNumber) {
375+ // Select a Country if prefix of decoration is add
376+ // if we take the prefix from current local or country selected
377+ if (widget.decoration.prefix != null ) {
378+ countrySelected = CountryService ().findCountryByPrefix (widget.decoration.prefix! ) ?? Country .empty ();
379+ } else {
380+ countrySelected = widget.countrySelector? .selectedCountry ?? Country .empty ();
381+ }
382+ // Clean the input to keep only digits
383+ final digitsOnly = value.replaceAll (RegExp (r'\D' ), '' );
384+
385+ // Retrieve the maximum allowed length for the selected country
386+ maxLength = getMaxDigitsFromLib (countrySelected.code);
387+ // Store the maximum length for future reference
388+ //maxLength = maxDigits;
389+
390+ // Limit the input to the maximum length
391+ limitedDigits = digitsOnly;
392+ if (maxLength != null && digitsOnly.length > maxLength! ) {
393+ limitedDigits = digitsOnly.substring (0 , maxLength);
394+ }
395+
396+ // Format the number
397+ try {
398+ if (widget.countrySelector == null ) {
399+ // Parse and format as national number if country selector is disabled
400+ final parsedNumber = phoneUtil.parse (limitedDigits, countrySelected.code.toUpperCase ());
401+ formattedNumber = phoneUtil.format (parsedNumber, PhoneNumberFormat .national);
402+ } else {
403+ // Parse and format as international number if country selector is enabled
404+ final parsedNumber = phoneUtil.parse (limitedDigits, countrySelected.code.toUpperCase ());
405+ String phoneNumber = phoneUtil.format (parsedNumber, PhoneNumberFormat .international);
406+ // Convert international number to national format
407+ formattedNumber = getNationalNumber (phoneNumber, countrySelected.code.toUpperCase ());
408+ }
409+
410+ // Update the controller's value with the formatted number
411+ final selectionIndex = widget.controller? .selection.baseOffset ?? 0 ;
412+
413+ widget.controller? .value = TextEditingValue (
414+ text: formattedNumber! ,
415+ // Keep the cursor position after the inserted formatted number
416+ selection: TextSelection .collapsed (offset: selectionIndex + (formattedNumber.length)),
417+ );
418+ } catch (e) {
419+ // If an error occurs during parsing or formatting, keep the raw digits
420+ widget.controller? .value = TextEditingValue (
421+ text: limitedDigits,
422+ // Place cursor at the end of the input
423+ selection: TextSelection .collapsed (offset: limitedDigits.length),
424+ );
425+ }
426+ }
427+
414428 /// Builds the prefix text widget for the text input field based on the current state.
415429 ///
416430 /// This method determines and displays the textual prefix to be shown
0 commit comments