jackocnr / intl-tel-input

A JavaScript plugin for entering and validating international telephone numbers. React and Vue components also included.
https://intl-tel-input.com
MIT License
7.69k stars 1.95k forks source link

Flag switches automatically while typing phone number #1866

Open MaartenPetiet opened 3 weeks ago

MaartenPetiet commented 3 weeks ago

Plugin version

v24.6.0

Steps to reproduce

  1. Open dropdown and select "Aland Islands"
  2. Start typing phone number "457"
  3. Flag switches to Finland

Expected behaviour

I'm not sure if this is a bug or feature, but I would expect that that the flag never switches without the user explicitly doing that. If the typed phone number does not comply with the formatting rules of that region it should trigger a validation message.

Actual behaviour

The flag switches to the Finnish flag.

Initialisation options

Setting separateDialCode: true will trigger this behavior. With seperateDialCode: false it doesn't do this, which leads me to suspect this is a bug.

jackocnr commented 2 weeks ago

Hmm interesting. Thanks for raising this as it has highlighted a few issues that need addressing.

This is working as intended in the case of separateDialCode=true. It should also do the same when nationalMode=false, although I've just found an unrelated bug in this case (select Aland Islands, then type dial code +358, and it selects Finland), which we should fix. Ideally, in my opinion, it would also update the selected flag as you type with the default options (separateDialCode=false and nationalMode=true), but this is harder to achieve as area codes are more complicated to handle in national numbers e.g. in the UK, there is an extra digit ("0") inserted at the beginning of the area code. I think this should also be fixed, to make it consistent at least.

Additionally, I've just spotted another issue - this time the problem is with libphonenumber: when separateDialCode=true, and you select Aland Islands, the placeholder number starts with a 4, which is not a valid Aland Islands number - it's actually a Finnish number, and if you type it, it will (correctly) change the flag to Finland. The problem is the generated number we get from libphonenumber is incorrect, so we need to file an issue with them about that.

I would expect that that the flag never switches without the user explicitly doing that

The thing is, the user can always type a plus and then a new international dial code, which surely should change the selected flag, right? And if you accept that, then why stop there? e.g. both Bahamas and Bermuda have the +1 dial code, but if you type +1242 then that can only be a Bahamas number, or +1441 can only be a Bermuda number, so why not update the flag?

If the typed phone number does not comply with the formatting rules of that region it should trigger a validation message

It seems strange to me to let the user type a full valid number, and then fail validation because it doesn't match the selected flag. Then what does the error message say - please update the flag selection to match the typed number? That seems quite annoying for the user.

To be clear, we're talking about an edge case here, because to follow your steps to reproduce - if you select Aland Islands and then type 457, you're not typing an Aland Islands number - you're typing a Finish number, so the user is already behaving strangely here.

What do you think?

MaartenPetiet commented 2 weeks ago

Thanks for your detailed reply @jackocnr. I am mainly aiming for consistency here, so that you found some issues here that can be improved helps a lot!

To be clear, we're talking about an edge case here, because to follow your steps to reproduce - if you select Aland Islands and then type 457, you're not typing an Aland Islands number - you're typing a Finish number, so the user is already behaving strangely here.

I agree. This is definitely an edge case, so if this is something that would cost way too much time to fix/change I would totally understand.

It seems strange to me to let the user type a full valid number, and then fail validation because it doesn't match the selected flag. Then what does the error message say - please update the flag selection to match the typed number? That seems quite annoying for the user.

Yes that's an interesting and valid point. I agree that it would be annoying if a user needs to change the flag just to get the validation to succeed. The reason I am/was expecting an error message is that I assume a user doesn't select the wrong region by accident. If the user then makes a typo and we can catch that, that would be great. But I acknowledge this is an assumption of mine. Maybe a user just clicks the first correct dial code it sees and doesn't mind which region it shows. Then it would definitely be annoying if we would force the user to change it.

I see pros and cons for both methods and just wanted to confirm that this behavior is expected. Whatever method you think is best works for me!

jackocnr commented 2 weeks ago

I assume a user doesn't select the wrong region by accident. If the user then makes a typo

Hmm in this case, if the user selects the correct flag, and then makes a typo in the number which changes the flag, I would say it is likely they will see that the flag changed, so it is a useful feature as it helps them to see that they have made a mistake.

I see pros and cons for both methods

I agree, and I think on balance, I will keep the current functionality, of automatically updating the flag as you type, and we should just fix the issues/inconsistencies we found along the way! To be clear they are:

Bug: when nationalMode=false, select Aland Islands, then type dial code +358, and it selects Finland. In this case, the user has just selected their country and typed the correct dial code, so it should respect their selection! The problem is, when you type +3, this is not a valid dial code, so it displays the globe icon, and then when you finish typing +358, it selects the "priority" country for that dial code, which is Finland. I think the ideal solution, in this case, would be: When the user types +3, before resetting to the globe icon, check if the typed dial code is a subset of the dial code for the currently selected country, and if so, leave that country selected. If that functionality is not possible for some reason, then I think we should remember the most recently selected country, and if the user types a dial code, before just defaulting to the top priority country for that dial code, we should check if it matches the most recently selected country and if so, show that one instead.

Inconsistency: with the default options (separateDialCode=false and nationalMode=true), it does not automatically update the selected flag as you type different area codes, because this is much harder with national numbers, due to national prefixes (and maybe some other countries have more complicated rules, I'm not sure). I would propose we review all the countries where we store area code information and read up about those countries' national phone number rules to determine if this functionality is realistic or not.

Libphonenumber bug: when separateDialCode=true, and you select Aland Islands, the placeholder number starts with a 4, which is not a valid Aland Islands number (and so if you type the 4, the flag correctly changes to Finland). We should report this issue to libphonenumber.

Unfortunately, I don't have time to look into these things right now, but I would welcome a pull request!

jackocnr commented 2 weeks ago

UPDATE: for reference, there are 36 countries where we store area code information, and 24 of those are NANP countries, which don't have any national number prefixes, so they should be trivial to get working. Here are the other 12 countries:

Screenshot 2024-11-06 at 18 41 51

So we'd need to check the national number rules for all of these countries (/territories/regions).

jackocnr commented 2 weeks ago

I found some time to review this, here are the results:

No national prefix:

National prefix "0":

National prefix "8":

So we'll need to encode this national prefix digit in the country data, and then hopefully all that is required is updating _getCountryFromNumber where we currently add the "+1" dial code for NANP countries, to instead add the intl dial code for all numbers (regardless of country), and also, if it's a country with a national prefix digit, then we should remove that before trying to match it.

Again, I don't have time to implement this change myself right now, but I would welcome a pull request.