NOTE: Error state is handled by default, validating length (too long or too short) relative to the selected country’s phone format and enforcing numeric-only values for all countries.
Preferred countries will display in the order they are listed with the first country preselected, and all non-preferred countries listed alphabetically below in the remaining dropdown.
Setting an initial country preselects that country within the input as well as the country dropdown.
Limiting countries removes all countries from the dropdown except your selections.
Excluding countries removes the selected countries from the dropdown.
<form id="example-form-validation" action="" method="get"> <%= pb_rails("phone_number_input", props: { id: "validation", initial_country: "af", value: "", required: true }) %> <%= pb_rails("button", props: {html_type: "submit", text: "Save Phone Number"}) %> </form> <%= javascript_tag do %> document.addEventListener('DOMContentLoaded', function () { const form = document.querySelector('#example-form-validation'); // Wait for React component to mount function waitForComponent() { const phoneInput = form.querySelector('#validation'); if (!phoneInput) { setTimeout(waitForComponent, 100); return; } // Wait for intl-tel-input to initialize, then focus and blur to trigger validation setTimeout(function() { phoneInput.focus({ preventScroll: true }); setTimeout(function() { phoneInput.blur(); }, 100); }, 500); } waitForComponent(); // Prevent form submission if there are validation errors form.addEventListener('submit', function (e) { if (e.target.querySelectorAll('[error]:not([error=""])').length > 0) { e.preventDefault(); } }); }) <% end %>
NOTE: the number in the React onChange event will not include formatting (no spaces, dashes, and parentheses). For Rails, the value will include formatting and its value must be sanitized manually.
<%= pb_rails("phone_number_input", props: { id: "phone_number_input", format_as_you_type: true }) %> <%= pb_rails("button", props: {id: "clickable", text: "Save Phone Number"}) %> <%= javascript_tag do %> document.querySelector('#clickable').addEventListener('click', () => { const formattedPhoneNumber = document.querySelector('#phone_number_input').value const unformattedPhoneNumber = formattedPhoneNumber.replace(/\D/g, "") alert(`Formatted: ${formattedPhoneNumber}. Unformatted: ${unformattedPhoneNumber}`) }) <% end %>
Ignore any irrelevant characters and cap the length at the maximum valid number length.
This can be combined with format_as_you_type / formatAsYouType.
The hidden_inputs boolean prop generates two hidden input fields, {field_name}_full and {field_name}_country_code. The value passed when the form is submitted contains the full phone number including the country code. Because it requires the submission of a form to function, only use this prop on Rails phone number elements within html form tags <form>/<form> or pb_forms. Read the intl-tel-input docs for more information.
Set country_search / countrySearch to true to allow users to search for a specific Country within the dropdown. If the range of countries has been limited, only the selected countries will be searchable.
The requiredIndicator/required_indicator prop displays a red asterisk (*) next to the label, visually indicating that the field is required. This is purely visual and does not enforce validation.
You can use requiredIndicator/required_indicator with any validation approach: HTML5 validation via the required prop, client-side validation, or backend validation. For this reason, it works independently and doesn't need to be paired with the required prop.
| Props | Type | Values |
|---|---|---|
align_content |
enum | responsive
|
start
end
center
spaceBetween
spaceAround
spaceEvenly
|
align_items |
enum | responsive
|
start
end
center
|
border_radius |
enum
|
none
xs
sm
md
lg
xl
rounded
|
cursor |
enum
|
auto
default
none
contextMenu
help
pointer
progress
wait
cell
|
dark |
boolean
|
true
false
|
flex |
enum | responsive
|
auto
initial
0
1
2
3
4
5
6
7
8
9
10
11
12
none
|
flex_direction |
enum | responsive
|
row
column
rowReverse
columnReverse
|
flex_wrap |
enum | responsive
|
wrap
nowrap
wrapReverse
|
justify_content |
enum | responsive
|
start
end
center
spaceBetween
spaceAround
spaceEvenly
|
line_height |
enum
|
loosest
looser
loose
normal
tight
tighter
tightest
|
margin_right |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_left |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_top |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_bottom |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_x |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_y |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin |
array
|
none
xxs
xs
sm
md
lg
xl
|
width |
string
|
|
min_width |
string
|
|
max_width |
string
|
|
gap |
string | responsive
|
|
column_gap |
string | responsive
|
|
row_gap |
string | responsive
|
|
number_spacing |
enum
|
tabular
|
order |
enum | responsive
|
none
first
1
2
3
4
5
6
7
8
9
10
11
12
|
overflow_x |
enum
|
scroll
visible
hidden
auto
|
overflow_y |
enum
|
scroll
visible
hidden
auto
|
overflow |
enum
|
scroll
visible
hidden
auto
|
padding_right |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_left |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_top |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_bottom |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_x |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_y |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding |
array
|
none
xxs
xs
sm
md
lg
xl
|
position |
enum
|
relative
absolute
fixed
sticky
static
|
shadow |
enum
|
none
deep
deeper
deepest
|
text_align |
enum | responsive
|
start
end
left
right
center
justify
justifyAll
matchParent
|
truncate |
enum
|
none
1
2
3
4
5
|
vertical_align |
enum | responsive
|
baseline
super
top
middle
bottom
sub
text-top
text-bottom
|
z_index |
enum | responsive
|
1
2
3
4
5
6
7
8
9
10
max
|
top |
enum | object
|
xxs
xs
sm
md
lg
xl
xxl
|
inset |
boolean
|
true
false
|
right |
enum | object
|
xxs
xs
sm
md
lg
xl
xxl
|
bottom |
enum | object
|
xxs
xs
sm
md
lg
xl
xxl
|
left |
enum | object
|
xxs
xs
sm
md
lg
xl
xxl
|
height |
string
|
|
max_height |
string
|
|
min_height |
string
|
|
hover |
object
|
|
group_hover |
boolean
|
true
false
|
| Props | Type | Values | Default |
|---|---|---|---|
disabled |
boolean
|
true
false
|
false
|
error |
string
|
||
hidden_inputs |
boolean
|
true
false
|
false
|
initial_country |
string
|
||
is_valid |
function
|
||
label |
string
|
||
name |
string
|
||
on_change |
reactnode
|
||
on_validate |
callback<boolean, void>
|
||
only_countries |
array
|
||
exclude_countries |
array
|
||
preferred_countries |
array
|
||
required |
boolean
|
true
false
|
false
|
required_indicator |
boolean
|
true
false
|
false
|
value |
string
|
||
format_as_you_type |
boolean
|
true
false
|
false
|
strict_mode |
boolean
|
true
false
|
false
|
country_search |
boolean
|
true
false
|
false
|