联系表格7收件人的动态数量

dav*_*all 7 wordpress contact-form-7

我在一个表格上工作,其核心是两个字段集:主要和"其他收件人"; 在"其他收件人"字段集的末尾,我有一个"添加另一个收件人"链接.

这是谁需要什么:

主要收件人:一切

其他收件人: "其他收件人"字段集;

后续收件人:各自的字段集

到目前为止,我一直在查看文档但在那里没有太多运气,也不是我所期望的.


编辑

我认为这还不清楚,所以我会更明确地说明背景是什么.我form是一个注册,我们可以注册多个人; 其中一个字段标有"您的电子邮件".由于我们可以同时注册多个人,因此我需要复制fieldset包含"您的电子邮件".


编辑2

为了帮助澄清,想象一下,我们正在为夏令营注册孩子.第一个fieldset是通用的,比如父母的账单信息,第二个fieldset是孩子的信息.父母需要能够填写单个form并动态添加与父母愿望一样多的孩子.

在每个孩子中fieldset,他们的电子邮件都是必需的,他们会收到与这个孩子相关的信息,其中的电子邮件类似于:

Hello {children's name},

You've been registered to StackOverflow Summer Camp. Here's the information you need to know:

[...]

Thanks for being a good sport!
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

Cam*_*urd 3

当您有这样的特定用例时,将功能硬塞到外围相关插件中通常会导致挫败感。话虽这么说 - 有时您会与特定的插件或方法结合在一起,并且只需要在它的基础上进行构建。

排除了这一警告后,我认为您应该从为 Contact Form 7创建新字段类型的角度来解决这个问题。这样您就可以控制字段 HTML 的呈现、数据验证等。正如您在另一个答案的评论中提到的那样,它还可能为数据库存储和稍后发送提醒提供启动点。

这是这种方法的实际应用:

测试 CF7 重复

新的字段类型称为emailplus,您可以将其包含到如下形式的表单中:

<div class="cf7-duplicable-recipients">
    <label>Main Recipient (required)</label>
    [emailplus emails]
    [submit "Sign Up"]
</div>
Run Code Online (Sandbox Code Playgroud)

此外,我已将表单设置中“邮件”面板下的收件人设置为[emails]

如果将某个emailsplus字段设置为收件人,则该类将覆盖默认的 wpcf7 行为并将邮件发送到数组中的每个值email,并按每个电子邮件替换消息正文中的任何 [emails] 占位符。

这里fieldtypeemailplus被封装在一个类中,并进行了自由注释:

<?php

class WPCF7_Duplicable_Email
{
    /**
     * The emails this form's field is addressed to
     *
     * @var array
     */
    public $emails = array();

    /**
     * The name of the tag bearing the emailplus type
     *
     * @var string
     */
    public $tag_name;

    /**
     * Instantiate the class & glom onto the wpcf7 hooks
     *
     * @return void
     */
    public function __construct()
    {
        add_action('wpcf7_init', array($this, 'add_emailplus_tag'));
        add_action('wpcf7_form_tag', array($this, 'assign_values_to_field'));
        add_filter('wpcf7_validate_emailplus', array($this, 'validate'), 2);
        add_action('wpcf7_before_send_mail', array($this, 'send_email'));
        add_action('wp_enqueue_scripts', array($this, 'emailplus_scripts'));
    }

    /**
     * Add our the [emailplus __YOUR_FIELD_NAME__] shortcode for use in wpcf7 forms.
     *
     * @uses wpcf7_add_shortcode
     *
     * @return void
     */
    public function add_emailplus_tag()
    {
        wpcf7_add_shortcode(
            array('emailplus'),
            array($this, 'shortcode_handler'),
            true
        );
    }

    /**
     * Renders the HTML for the [emailplus] shortcode
     *
     * Referenced from wpcf7_text_shortcode_handler in wp-content/plugins/contact-form-7/modules/text.php
     *
     * @param array $tag The data relating to the emailplus form field.
     *
     * @uses wpcf7_get_validation_error
     * @uses wpcf7_form_controls_class
     *
     * @return string
     */
    public function shortcode_handler(array $tag) {
        $tag = new WPCF7_Shortcode($tag);

        if (true === empty($tag->name)) {
            return '';
        }

        $validation_error = wpcf7_get_validation_error($tag->name);
        $class            = wpcf7_form_controls_class($tag->type);

        if ($validation_error) {
            $class .= ' wpcf7-not-valid';
        }

        $atts = array(
            'class'        => $tag->get_class_option($class),
            'id'           => $tag->get_id_option(),
            'tabindex'     => $tag->get_option('tabindex', 'int', true),
            'aria-invalid' => $validation_error ? 'true' : 'false',
            'type'         => 'email',
            'name'         => $tag->name.'[]', // <-- Important! the trailing [] Tells PHP this is an array of values
            'value'        => $tag->get_default_option()
        );

        $atts = wpcf7_format_atts($atts);

        $html = sprintf(
            '<div class="emailplus-wrapper %1$s"><input %2$s />%3$s</div>',
            sanitize_html_class($tag->name),
            $atts,
            $validation_error
        );

        // We identify the container that will hold cloned fields with the [data-wpcf7-duplicable-email] attr
        return '<div class="wpcf7-form-control-wrap %1$s" data-wpcf7-duplicable-email>'.$html.'</div>';
    }

    /**
     * Validates the value of the emailplus tag.
     *
     * Must be handled separately from other text-based form inputs,
     * since the submitted POST value is an array.
     *
     * We can safely assume emailplus while creating the WPCF7_Shortcode,
     * because we know we hooked this function onto 'wpcf7_validate_emailplus'
     *
     * @uses wpcf7_is_email
     * @uses WPCF7_Validation::invalidate
     *
     * @param WPCF7_Validation $result The validation helper class from wpcf7.
     * @param array            $tag    The array of values making up our emailplus tag
     *
     */
    public function validate(WPCF7_Validation $result, $tag)
    {
        $tag = new WPCF7_Shortcode(
            array(
                'basename' => 'emailplus',
                'name' => $this->tag_name,
                'raw_values' => $this->emails
            )
        );

        // Check each value of the form field.
        // Emails must be validated individually.
        foreach($tag->raw_values as $email) {
            if (false === wpcf7_is_email($email)) {
                $result->invalidate($tag, wpcf7_get_message('invalid_email'));
            }
        }

        return $result;
    }

    /**
     * For completeness' sake, manually assign the value to the emailplus fieldtype.
     *
     * Wpcf7 doesn't know how to treat our fieldtype's value by default.
     *
     * As a side effect, this sets the email addresses that are up for delivery.
     *
     * @param array $scanned_tag The tag that wpcf7 is scanning through, and processing.
     *
     * @return $array;
     */
    public function assign_values_to_field($scanned_tag)
    {
        if ($scanned_tag['type'] !== 'emailplus') {
            return $scanned_tag;
        }

        $this->tag_name = $scanned_tag['name'];

        if (key_exists($scanned_tag['name'], $_POST)) {
            // Stores the emails on a class property for use later.
            $this->emails = $_POST[$scanned_tag['name']];
            $scanned_tag['raw_values'] = $this->emails;
            $scanned_tag['values']     = $this->emails;
        }

        return $scanned_tag;
    }

    /**
     * Performs a substitution on the emailplus field's fieldname, on a per-value basis.
     *
     * Ex. in two parts
     *  1 - The shortcode [emailsplus emails] renders into <input type="email" name="emails[]" value="" >
     *      Which the user clones and submits, processing into something like
     *      ['test1@gmail.com', 'test2@gmail.com'].
     *  2 - The user has set [emails] as the recipient in the "mail" panel for the form.
     *
     * Because wpcf7 isn't aware of how to process a field w/ multiple values when emailing,
     * we loop over the values of [emails], replace the tag, and invoke WPCF7_Mail::send()
     * for each value.
     *
     * @param WPCF7_ContactForm $form The contact form object.
     *
     * @uses WPCF7_Mail::send
     *
     * @return void
     */
    public function send_email(WPCF7_ContactForm $form)
    {
        $placeholder = '['.$this->tag_name.']';

        if (false === strpos($form->prop('mail'), $placeholder)) {
            return;
        }

        foreach ($this->emails as $email) {
            $template = $form->prop('mail');
            $template['recipient'] = str_replace($placeholder, $email, $template['recipient']);
            $template['body']      = str_replace($placeholder, $email, $template['body']);
            WPCF7_Mail::send($template);
        }

        // Tell cf7 to skip over the default sending behaviour in WPCF7_Submission->mail()
        $form->skip_mail = true;
    }

    /**
     * Adds our js that will clone the emailplus field.
     *
     * Could be optimized with a conditional that checks if there is a form with the [emailplus]
     * fieldtype somewhere on the page
     *
     * @return void
     */
    public function emailplus_scripts()
    {
        wp_enqueue_script(
            'cf7-duplication',
            get_template_directory_uri() . '/js/cf7-duplication.js',
            array('jquery'),
            '20161006',
            true
        );
    }
}

$wpcf7DuplicableEmail = new WPCF7_Duplicable_Email();
Run Code Online (Sandbox Code Playgroud)

并且,处理克隆的 .js 文件。它应该住在/path/to/your/theme/js/cf7-duplication.js'.

(function($) {
  $(document).ready(function() {
    var addEmailField = function(inputRow, container) {
      inputRow.find('input[type=email]').val('');

      var removeButton = $('<a href="#">&times;</a>')
        .click(function(e) {
          e.preventDefault();
          inputRow.remove();
        });

      inputRow.append(removeButton);
      inputRow.insertAfter(container.find('.emailplus-wrapper').last());
    }

    $.each($('[data-wpcf7-duplicable-email]'), function(i, el) {
      var container = $(el);
      var inputRow  = container.find('.emailplus-wrapper');
      var addButton = $('<a href="#">Add another email</a>');

      addButton.click(function(e) {
        e.preventDefault();
        var newEmailField = inputRow.clone();
        addEmailField(newEmailField, container);
      });

      container.append(addButton);
    });
  });
})(jQuery);
Run Code Online (Sandbox Code Playgroud)

最后但并非最不重要的一点是,如果您希望表单在有效且电子邮件已发出时淡出,请将其添加到“其他设置”面板。

on_sent_ok: "jQuery('.cf7-duplicable-recipients').fadeOut();"
Run Code Online (Sandbox Code Playgroud)

此方法最适合 CF7 的AJAX提交。如果您想扩展它来处理普通的 POST 请求,您可以更新短代码处理程序以呈现多个<input>字段,在这些字段中您需要保留value无效提交的 attr。