$postal_placeholder = ! empty( $field['postal_placeholder'] ) ? $field['postal_placeholder'] : '';
$postal_default = ! empty( $field['postal_default'] ) ? $field['postal_default'] : '';
$postal_hide = ! empty( $field['postal_hide'] ) ? 'wpforms-hide' : '';
$country_hide = ! empty( $field['country_hide'] ) ? 'wpforms-hide' : '';
$format = ! empty( $field['format'] ) ? $field['format'] : 'us';
$scheme_selected = ! empty( $field['scheme'] ) ? $field['scheme'] : $format;
$this->field_preview_option(
'label_badge' => $this->get_field_preview_badge(),
foreach ( $this->schemes as $slug => $scheme ) {
$address1_label = $scheme['address1_label'] ?? esc_html__( 'Address Line 1', 'wpforms-lite' );
$address2_label = $scheme['address2_label'] ?? esc_html__( 'Address Line 2', 'wpforms-lite' );
$city_label = $scheme['city_label'] ?? esc_html__( 'City', 'wpforms-lite' );
$state_label = $scheme['state_label'] ?? esc_html__( 'State / Province / Region', 'wpforms-lite' );
$postal_label = $scheme['postal_label'] ?? esc_html__( 'Postal Code', 'wpforms-lite' );
$country_label = $scheme['country_label'] ?? esc_html__( 'Country', 'wpforms-lite' );
$is_active_scheme = $slug === $scheme_selected;
$scheme_hide_class = ! $is_active_scheme ? 'wpforms-hide' : '';
$state_placeholder = ! empty( $field['state_placeholder'] ) ? $field['state_placeholder'] : '';
$state_default = $is_active_scheme && ! empty( $field['state_default'] ) ? $field['state_default'] : '';
$country_placeholder = ! empty( $field['country_placeholder'] ) ? $field['country_placeholder'] : '';
$country_default = $is_active_scheme && ! empty( $field['country_default'] ) ? $field['country_default'] : '';
'<div class="wpforms-address-scheme wpforms-address-scheme-%s %s">',
wpforms_sanitize_classes( $slug ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
wpforms_sanitize_classes( $scheme_hide_class ) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
// Row 1 - Address Line 1.
'<div class="wpforms-field-row wpforms-address-1">
<input type="text" placeholder="%s" value="%s" readonly>
<label class="wpforms-sub-label">%s</label>
esc_attr( $address1_placeholder ),
esc_attr( $address1_default ),
esc_html( $address1_label )
// Row 2 - Address Line 2.
'<div class="wpforms-field-row wpforms-address-2 %s">
<input type="text" placeholder="%s" value="%s" readonly>
<label class="wpforms-sub-label">%s</label>
wpforms_sanitize_classes( $address2_hide ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
esc_attr( $address2_placeholder ),
esc_attr( $address2_default ),
esc_html( $address2_label )
echo '<div class="wpforms-field-row">';
'<div class="wpforms-city wpforms-one-half ">
<input type="text" placeholder="%s" value="%s" readonly>
<label class="wpforms-sub-label">%s</label>
esc_attr( $city_placeholder ),
esc_attr( $city_default ),
// State / Providence / Region.
echo '<div class="wpforms-state wpforms-one-half last">';
if ( isset( $scheme['states'] ) && empty( $scheme['states'] ) ) {
printf( '<input type="text" placeholder="%s" value="%s" readonly>', esc_attr( $state_placeholder ), esc_attr( $state_default ) );
} elseif ( ! empty( $scheme['states'] ) && is_array( $scheme['states'] ) ) {
$state_option = $this->dropdown_empty_value( (string) $state_label );
if ( ! empty( $state_placeholder ) ) {
$state_option = $state_placeholder;
if ( $is_active_scheme && ! empty( $state_default ) ) {
$state_option = $scheme['states'][ $state_default ];
printf( '<select readonly> <option class="placeholder" selected>%s</option> </select>', esc_html( $state_option ) );
printf( '<label class="wpforms-sub-label">%s</label>', esc_html( $state_label ) );
// End row 3 - City & State.
// Row 4 - Zip & Country.
echo '<div class="wpforms-field-row">';
'<div class="wpforms-postal wpforms-one-half %s">
<input type="text" placeholder="%s" value="%s" readonly>
<label class="wpforms-sub-label">%s</label>
wpforms_sanitize_classes( $postal_hide ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
esc_attr( $postal_placeholder ),
esc_attr( $postal_default ),
esc_html( $postal_label )
printf( '<div class="wpforms-country wpforms-one-half last %s">', sanitize_html_class( $country_hide ) );
if ( isset( $scheme['countries'] ) && empty( $scheme['countries'] ) ) {
printf( '<input type="text" placeholder="%s" value="%s" readonly>', esc_attr( $country_placeholder ), esc_attr( $country_default ) );
} elseif ( ! empty( $scheme['countries'] ) && is_array( $scheme['countries'] ) ) {
$country_option = $this->dropdown_empty_value( (string) $country_label );
if ( ! empty( $country_placeholder ) ) {
$country_option = $country_placeholder;
if ( $is_active_scheme && ! empty( $country_default ) ) {
$country_option = $scheme['countries'][ $country_default ];
printf( '<select readonly><option class="placeholder" selected>%s</option></select>', esc_html( $country_option ) );
printf( '<label class="wpforms-sub-label">%s</label>', esc_html( $country_label ) );
// End row 4 - Zip & Country.
$this->field_preview_option( 'description', $field );
* Field display on the form front-end.
* @param array $field Field data and settings.
* @param array $deprecated Deprecated field attributes. Use field properties instead.
* @param array $form_data Form data and settings.
public function field_display( $field, $deprecated, $form_data ) {
* Output "Default" option fields for State/Country subfields.
* The default value should be set only for the scheme it belongs to.
* @param array $field Address field data.
* @param string $subfield_slug Subfield slug, either `state` or `country`.
* @param string $subfield_key Subfield key in `$scheme` data, either `states` or `countries`.
* @noinspection HtmlUnknownAttribute
private function subfield_default( array $field, string $subfield_slug, string $subfield_key ): void {
// Scheme or default value may not be set yet.
$active_scheme = ! empty( $field['scheme'] ) ? $field['scheme'] : 'us';
$default_value = ! empty( $field[ "{$subfield_slug}_default" ] ) ? $field[ "{$subfield_slug}_default" ] : '';
foreach ( $this->schemes as $scheme_slug => $scheme_data ) {
$subfield_label = empty( $scheme_data[ $subfield_slug . '_label' ] ) ? ucfirst( $subfield_slug ) : $scheme_data[ $subfield_slug . '_label' ];
$empty_value = $this->dropdown_empty_value( $subfield_label );
$is_active_scheme = $scheme_slug === $active_scheme;
// If a scheme contains an array of values, we display a select dropdown. Otherwise, text input.
if ( ! empty( $scheme_data[ $subfield_key ] ) && is_array( $scheme_data[ $subfield_key ] ) ) {
$options_escaped = sprintf( '<option value="">%s</option>', esc_html( $empty_value ) );
foreach ( $scheme_data[ $subfield_key ] as $value => $label ) {
$options_escaped .= sprintf(
'<option value="%s"%s>%s</option>',
$is_active_scheme ? selected( $default_value, $value, false ) : '',
if ( $is_active_scheme ) {
'<select class="default" id="wpforms-field-option-%1$s-%2$s_default" name="fields[%1$s][%2$s_default]" data-scheme="%3$s">%4$s</select>',
wpforms_validate_field_id( $field['id'] ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
esc_attr( $subfield_slug ),
esc_attr( $scheme_slug ),
$options_escaped // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
'<select class="default wpforms-hidden-strict" id="" name="" data-scheme="%s">%s</select>',
esc_attr( $scheme_slug ),
$options_escaped // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
if ( $is_active_scheme ) {
'<input type="text" class="default" id="wpforms-field-option-%1$s-%2$s_default" name="fields[%1$s][%2$s_default]" value="%3$s" data-scheme="%4$s">',
wpforms_validate_field_id( $field['id'] ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
esc_attr( $subfield_slug ),
esc_attr( $default_value ),
'<input type="text" class="default wpforms-hidden-strict" id="" name="" value="" data-scheme="%s">',
* Get a select dropdown "placeholder" option which is displayed if nothing is selected.
* @param string $name Select field name, can be lowercase or uppercase.
protected function dropdown_empty_value( string $name ): string {
return sprintf( /* translators: %s - subfield name, e.g., state, country. */
__( '--- Select %s ---', 'wpforms-lite' ),