😆Change date format contact form 7, Change placeholder, add attribute full (ok)

1. Thêm id và class

[text* Name id:name class:input_box placeholder "Name"]
<input type="text" onfocus="(this.type='date')" onblur="(this.type='text')"  name="FromDate" value="" class="wpcf7-form-control wpcf7-date wpcf7-validates-as-required wpcf7-validates-as-date" aria-required="true" aria-invalid="false" placeholder="Start Date">

add_filter( 'wpcf7_form_elements', 'imp_wpcf7_form_elements' );
function imp_wpcf7_form_elements( $content ) {
  $str_pos = strpos( $content, 'name="your-name"' ); //name='yourfield name'
  if ( $str_pos !== false ) {
      $content = substr_replace( $content, ' data-attr="custom" data-msg="Foo Bar 1" ', $str_pos, 0 );
  }
  return $content;
}

Sử dụng trực tiếp minlength:1 maxlength:10 dùng được nhưng sử dụng đoạn code sau lại không hoạt động tốt không biết có phải do bất đồng bộ gì đó không?

add_filter( 'wpcf7_form_elements', 'imp_wpcf7_form_elements' );
function imp_wpcf7_form_elements( $content ) {
  $str_pos = strpos( $content, 'id="your-name"' );
  if ( $str_pos !== false ) {
    $content = substr_replace( $content, 'pattern="[0-9]{10}" minlength="10" maxlength="10" ', $str_pos, 0 );
  }
  return $content;
}

Asked 5 years, 6 months agoModified 7 months agoViewed 21k times15

How to add a custom attribute in the field Contact Form 7 without javascript ?

For example, there is such a field on the page:

<input type="text" name="name" class="form-control" id="name-1" data-attr="custom" data-msg="Текст 1"> 

Question: is it possible to set these custom attributes (data-attr, data-msg) of fields in the admin panel?

Add a comment

6 Answers

Sorted by: Highest score (default) Trending (recent votes count more) Date modified (newest first) Date created (oldest first) 26

Find the name of your field.

[text* text-21]

If the name of your field name="text-21", like in my example, add this code to functions.php file.

add_filter( 'wpcf7_form_elements', 'imp_wpcf7_form_elements' );
function imp_wpcf7_form_elements( $content ) {
    $str_pos = strpos( $content, 'name="text-21"' );
    if ( $str_pos !== false ) {
        $content = substr_replace( $content, ' data-attr="custom" data-msg="Foo Bar 1" ', $str_pos, 0 );
    }
    return $content;
}

Note, it will add those attributes to all forms elements where the name is text-21, if you want prevent it then give your form element some unique name [text* unique-name]

And change the code to

add_filter( 'wpcf7_form_elements', 'imp_wpcf7_form_elements' );
function imp_wpcf7_form_elements( $content ) {
    $str_pos = strpos( $content, 'name="unique-name"' );
    if ( $str_pos !== false ) {
        $content = substr_replace( $content, ' data-attr="custom" data-msg="Foo Bar 1" ', $str_pos, 0 );
    }
    return $content;
}
  • That filter add data-attr to everything, if field doesn't exists it prints "data-attr" ecc everywhere. How to fix? – Davide De Maestri Jan 17, 2018 at 10:57

  • It seems that you have forms with the same element names. Change field name to something unique. Please pay attention I edit my answer. – Oleg Apanovich Jan 23, 2018 at 21:04

  • 1This one helped great, to add autocomplete="both" autocomplete="off" to disable Chrome autofill dropdown for DATE selector field. Thanks! add_filter( 'wpcf7_form_elements', 'imp_wpcf7_form_elements' ); function imp_wpcf7_form_elements( $content ) { $str_pos = strpos( $content, 'name="date-from"' ); $content = substr_replace( $content, ' autocomplete="both" autocomplete="off" ', $str_pos, 0 ); $str_pos = strpos( $content, 'name="date-to"' ); $content = substr_replace( $content, ' autocomplete="both" autocomplete="off" ', $str_pos, 0 ); return $content; }Arnis Juraga Jul 9, 2019 at 17:42

  • Thanks Tofandel your remarks have sense I approved your answer editing, and it became better. – Oleg Apanovich Dec 20, 2019 at 20:21

Add a comment5

Here is a generic solution that doesn't involve hardcoding the field name and the attributes

add_filter( 'wpcf7_form_tag', function ( $tag ) {
    $datas = [];
    foreach ( (array)$tag['options'] as $option ) {
        if ( strpos( $option, 'data-' ) === 0 ) {
            $option = explode( ':', $option, 2 );
            $datas[$option[0]] = apply_filters('wpcf7_option_value', $option[1], $option[0]);
        }
    }
    if ( ! empty( $datas ) ) {
        $id = uniqid('tmp-wpcf');
        $tag['options'][] = "class:$id";
        add_filter( 'wpcf7_form_elements', function ($content) use ($id, $datas) {
            return str_replace($id, $name, str_replace($id.'"', '"'. wpcf7_format_atts($datas), $content));
        });
    }
    return $tag;
} );

It works on all data attributes so you can use it like this

[text* my-name data-foo:bar data-biz:baz placeholder "Blabla"]
Output: <input type="text" name="my-name" data-foo="bar" data-biz="baz" placeholder="Blabla">

Since wpcf7 doesn't provide a way to hook into options directly the solutions uses a trick and temporary adds a uniquely generated class to the field that is then replaced in a later filter with the added attributes

If you need it to work with more than just data attributes you can whitelist some more attributes by replacing this line

if ( strpos( $option, 'data-' ) === 0 ) {

to something like the following

if ( preg_match( '/^(data-|pattern|my-custom-attribute)/', $option ) ) {

Note: wpcf7_format_atts will not output empty attributes, so make sure you give a value to your attributes

  • Cannot get it to work with CF7 v5.1.8. data-* stuff is simply ignored. Did you test your solution with CF7 v5.1.8? – DarkLeafyGreen May 15, 2020 at 18:07

  • 1Yes, it still works, just make sure the attribute is right after the name and not after an attribute like placeholder "Blabla" or contact form will not parse the field at all (regex issue, not related to my code). I see no reason the backward compatibility for this filter will ever be broken as it's pretty low level – Tofandel May 16, 2020 at 16:55

  • thanks! How would you provide a pattern like [0-9()#&+*-=.]+? I tried it with your solution and the output could not be created. – DarkLeafyGreen May 20, 2020 at 9:58

  • $tag['name'] = $id = uniqid(); this part is wrong as it make the field id for the email part change to uniq id of the form isntade. So it should be - $tag['name'] = $id = $name; – Soykot Jun 29, 2020 at 21:29

  • 1Note that this solution breaks CF7's validation: invalid required input fields using custom data-* attributes won't be given the wpcf7-not-valid CSS class on submission. – cabrerahector Jul 2, 2020 at 20:10

Show 5 more comments3

Multiple attributes can be added also. eg

add_filter( 'wpcf7_form_elements', 'imp_wpcf7_form_elements' );

function imp_wpcf7_form_elements( $content ) {
    $str_pos = strpos( $content, 'name="your-email-homepage"' );
    $content = substr_replace( $content, ' aria-describedby="emailHelp" ', $str_pos, 0 );

    $str_pos2 = strpos( $content, 'name="your-fname-homepage"' );
    $content = substr_replace( $content, ' aria-describedby="fnameHelp" ', $str_pos2, 0 );

    $str_pos3 = strpos( $content, 'name="your-lname-homepage"' );
    $content = substr_replace( $content, ' aria-describedby="lnameHelp" ', $str_pos3, 0 );
    return $content;        
}

Extending on from Tofandel's solution, for the benefit of those who got 99% of the way there, but suffered validation issues - I've resolved that in my case and would like to offer an extended solution that gets as far as Tofandel's (putting the attribute into the form proper) but also successfully validates on submission.

    add_filter('wpcf7_form_tag', function($tag) {
      $data = [];
      foreach ((array)$tag['options'] as $option) {
        if (strpos( $option, 'autocomplete') === 0) {
          $option = explode(':', $option, 2);
          $data[$option[0]] = apply_filters('wpcf7_option_value', $option[1], $option[0]);
        }
      }
      if(!empty($data)) {
        add_filter('wpcf7_form_elements', function ($content) use ($tag, $data) {
          $data_attrs = wpcf7_format_atts($data);
          $name = $tag['name'];
          $content_plus_data_attrs = str_replace("name=\"$name\"", "name=\"$name\" " . $data_attrs, $content);

          return $content_plus_data_attrs;
        });
      }
      return $tag;
    } );

Rather than changing the tag ID to a random value only to replace it with the "real" value later, we just reference the real value in the first place, replacing the relevant part of the content in the wpcf7_form_elements filter (in my case, autocomplete, but as Tofandel's example shows, this can be extended to any data attribute you'd like).

  • Just FYI, I didn't do it like this because I needed to support multiple contact forms on a same page, and this will mix up the attributes between them – Tofandel Sep 7, 2022 at 23:11

  • I updated my answer to add a unique class and use that instead of changing the tag name, which should take care of both problems – Tofandel Sep 7, 2022 at 23:40

Add a comment0

I propose a solution from the one given by Tofandel without JS (CF7) error and to authorize the use of an attribute without value:

/**
 * Add custom attributes on inputs
 * Put "data-my-attribute" to use it, with or without value
 *
 * @param array $tag
 *
 * @return array
 */
function cf7AddCustomAttributes($tag) {
    $datas = [];

    foreach ((array) $tag['options'] as $option) {
        if (strpos($option, 'data-') === 0 || strpos($option, 'id:') === 0) {
            $option = explode(':', $option, 2);
            $datas[$option[0]] = apply_filters('wpcf7_option_value', $option[1], $option[0]);
        }
    }

    if (!empty($datas)) {
        $id = $tag['name'];

        if (array_key_exists('id', $datas)) {
            $id = $datas['id'];
        } else {
            $tag['options'][] = "id:$id";
        }

        add_filter('wpcf7_form_elements', function ($content) use ($id, $datas) {
            $attributesHtml = '';
            $idHtml = "id=\"$id\"";

            foreach ($datas as $key => $value) {
                $attributesHtml .= " $key";

                if (is_string($value) && strlen($value) > 0) {
                    $attributesHtml .= "=\"$value\"";
                }
            }

            return str_replace($idHtml, "$idHtml $attributesHtml ", $content);
        });
    }

    return $tag;
}
add_filter('wpcf7_form_tag', 'cf7AddCustomAttributes');

I use this simple method for setting attribute

[checkbox optName use_label_element "optName"]
<script>
document.querySelector(".optName").setAttribute("onchange","myscript");
</script>

Last updated