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.66k stars 1.95k forks source link

How to get Country code to populate on validation failure when phone number is populated #715

Closed irfman12 closed 6 years ago

irfman12 commented 6 years ago

IMPORTANT: please note that the autoFormat feature (format-as-you-type) was removed in v8.0.0 - read more here: https://github.com/jackocnr/intl-tel-input/issues/346. Please do not open any new issues about this topic.

IMPORTANT: we use libphonenumber for formatting and validation - if your issue relates to one of these things, please check their test site first and if you see the problem there please file an issue with them instead: https://rawgit.com/googlei18n/libphonenumber/master/javascript/i18n/phonenumbers/demo-compiled.html

Steps to reproduce

  1. Wrap Phone number field on form
  2. Have error Validations based on Submit function
  3. Cause error validation on some other field

Expected behaviour

When form reloads, it shoudl automatically select country code because it was populated, along with phone number

Actual behaviour

form reloads, with phone number field populated, but country dial code is not selected,

Initialisation options

(function () {
    if ($("#NewUser_PhoneNumber") != null && $("#NewUser_PhoneNumber") != undefined) {
        $("#NewUser_PhoneNumber").intlTelInput({
            separateDialCode: true,
            hiddenInput: "NewUser_PhoneFullNumber",
            nationalMode: true,
            initialCountry: "auto",
            geoIpLookup: function (callback) {
                $.get('https://ipinfo.io', function () { }, "jsonp").always(function (resp) {
                    var countryCode = (resp && resp.country) ? resp.country : "";
                    callback(countryCode);
                });
            },
            utilsScript: "js/utils.js"
        });
        $.validator.addMethod('phonenumber',
            function (value, element, params) {
                var telInput = $(element);
                var countryCode = telInput.intlTelInput("getSelectedCountryData");
                $("#NewUser_PhoneIso2").val(countryCode.iso2);
                $("#NewUser_PhoneDailCode").val(countryCode.dialCode);
                return telInput.intlTelInput("isValidNumber");
            });
        $.validator.unobtrusive.adapters.addBool('phonenumber');
    }
jackocnr commented 6 years ago

Hi there. What do you mean by "When form reloads"? Do you mean when you reload the page? If so, how are you adding the number in your form? In the html input value attribute? Or are you setting it using JS (and if so how)? Also please give me an example of a phone number that you're using that isn't working.

(I'm afraid I'm not familiar with $.validator, so I don't know when the code inside that block is run)

irfman12 commented 6 years ago

unfortunately can't share the whole form. I have one big form validation. So, if any field example name is invalid my form submittal goes to error state,

This where I think the problem is in js

    handleAutoCountry: function() {
        if (this.options.initialCountry === "auto") {
            // we must set this even if there is an initial val in the input: in case the initial val is invalid and they delete it - they should see their auto country
            this.defaultCountry = $.fn[pluginName].autoCountry;
            // if there's no initial value in the input, then update the flag
            if (!this.telInput.val()) {
                this.setCountry(this.defaultCountry);
            }
            this.autoCountryDeferred.resolve();
        }
    },

I need to add an else to retrieve defaultCountry from the form, or it should auto populate. if (!this.telInput.val()) { this.setCountry(this.defaultCountry); } need an else here as this.defaultCountry ends up being null. this is a snippet of the form

@*Please include country code. Ex: +12451239876
*@
irfman12 commented 6 years ago

So, I'm using hiddeninput to do a post, I have other validations that need to be done, if any validations fail, I'm able to get the value of PhoneNumber, but I lose the selectedCountry. I hope that explains it. What I need is ability to set the selected Country via country code etc.. after I do my form post.

jackocnr commented 6 years ago

Are you dealing in full international numbers e.g. "+447947123456"? This is how we recommend you use the plugin. You can get the number in this format even when using nationalMode by using the getNumber method. Then if you set the number in the input using our setNumber method, it will automatically set the country too.

irfman12 commented 6 years ago

Not exactly. I'm using the country drop down, with auto country code, via geoIp

So, the drop drown populates, on first load, with country based on ip. I want to change the country code to something else, I do manually, then I put it in thre rest of the number. and I use the hiddeninput to get the full number via getNumber() automatically on my form post, when I return back to form due to any post validation error on server for any other reason. the country does not populate because the number is populated with just 7947123456, since we have the drop down, we don't want the full number to show in the input box +447947123456

BAsically I want the functionality of https://intl-tel-input.com/node_modules/intl-tel-input/examples/gen/hidden-input.html but remember my choice if different on submit (if there is any validation error on server side) for other reasons besides phone number. that's the best I can explain it.

jackocnr commented 6 years ago

we don't want the full number to show in the input box +447947123456

It wont. If you have nationalMode enabled (it is by default), then when you call setNumber with "+447947123456" it will automatically convert it to a national number, namely "07947123456" (assuming you have utils.js loaded - also recommended).

irfman12 commented 6 years ago

okay, I have nationalMode set to true, so you are saying before we do our form submit I should call setNumber? I do have both formatOnDisplay to true and nationalMode set to true, so I'm not understanding what I'm missing.

irfman12 commented 6 years ago

I think the problem is that when I initialize, with the input box field, example based on your example above https://intl-tel-input.com/node_modules/intl-tel-input/examples/gen/hidden-input.html

phone number is full format in javascript but when I form submit, and error back, I reinitialize not on fullphonenumber the hidden field but the active field.

irfman12 commented 6 years ago

I guess I need a way to get country code out of the hidden field fullphonenumber

jackocnr commented 6 years ago

Don't worry about the hidden field - you shouldn't be touching that - leave it to the plugin. You just re-initialise the plugin with the full international number and everything should be fine.

If you're still having problems, can I ask that you break it down into really clear simple steps, with example numbers etc, as I'm struggling to understand exactly where the problem is.

irfman12 commented 6 years ago

got it, I understand it's super difficult over github, I wish I could share the full code. Thanks for your quick support it's a great plugin btw kudos.

irfman12 commented 6 years ago

Hey, I found a solution to my problem the issue, is when we do a post

After I throw a validation error on Submit for a traditional form post. the library initalizes the value fron NewUser_PhoneNumber where the value is the formattedforDisplay in national mode.

I added a little bit of code, to set the value based on iso code, from a hidden field I had on the page that captured isocode. Please take a look below.

(function () {
    if ($("#NewUser_PhoneNumber") != null && $("#NewUser_PhoneNumber") != undefined) {
        $("#NewUser_PhoneNumber").intlTelInput({
            separateDialCode: true,
            hiddenInput: "NewUser_PhoneFullNumber",
            nationalMode: true,
            initialCountry: "auto",
            geoIpLookup: function (callback) {
                $.get('https://ipinfo.io', function () { }, "jsonp").always(function (resp) {
                    var countryCode = (resp && resp.country) ? resp.country : "";
                    callback(countryCode);
                });
            },
            utilsScript: "js/utils.js"
        });
        var isoValue = $("#NewUser_PhoneIso2").val();
        if (isoValue != undefined && isoValue !=null){
            $("#NewUser_PhoneNumber").intlTelInput("setCountry",isoValue);
        }
        $.validator.addMethod('phonenumber',
            function (value, element, params) {
                var telInput = $(element);
                var countryCode = telInput.intlTelInput("getSelectedCountryData");
                $("#NewUser_PhoneIso2").val(countryCode.iso2);
                $("#NewUser_PhoneDailCode").val(countryCode.dialCode);
                return telInput.intlTelInput("isValidNumber");
            });
        $.validator.unobtrusive.adapters.addBool('phonenumber');
    }

}(jQuery));
jackocnr commented 6 years ago

Sure, whatever works for you. If you're happy then feel free to close this issue.

But I would say: you really shouldn't need to be handling any extra fields like PhoneIso2 or PhoneDialCode (unless you need to use those values elsewhere in your app) - you should be able to just handle one string which is the full international phone number. If you have a full international number in the input when you init the plugin then it will automatically set the flag for you, and automatically re-format the number to national format for you e.g. if you init the plugin on an input with value "+447733123123" then it will automatically select UK flag and format the number as "07733123123".

jackocnr commented 6 years ago

Closing due to inactivity.