Token导航 LogoToken导航TokenDH.com
前端设计敏感数据github未标认证来源可访问许可证需确认审计通过

elementor-forms元素形式

Agent Skill

elementor-forms 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

279

周安装

12

GitHub Stars

3

下载量

98
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:elementor-forms(元素形式)
来源仓库:https://github.com/peixotorms/odinlayer-skills
仓库路径:skills/elementor-forms
安装命令:
npx skills add https://github.com/peixotorms/odinlayer-skills --skill elementor-forms
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/peixotorms/odinlayer-skills --skill elementor-forms

简介

elementor-forms 提供 Elementor Pro 表单动作扩展的开发接口与使用指南。

  • 适用于注册自定义表单行为、集成第三方服务或处理提交逻辑。
  • 通过 npx skills add 命令从 GitHub 安装,需确认仓库权限与网络访问能力。
  • 使用前应核实维护状态及是否涉及文件读写、命令执行等敏感操作。
  • 适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

SKILL.md

Elementor Forms Extension Reference

Elementor Pro only. All form APIs require Elementor Pro active.

1. Form Actions

Actions execute after form submission. Extend \ElementorPro\Modules\Forms\Classes\Action_Base.

Registration

add_action( 'elementor_pro/forms/actions/register', function ( $form_actions_registrar ) {
    require_once __DIR__ . '/form-actions/my-action.php';
    $form_actions_registrar->register( new \My_Custom_Action() );
});

Required Methods

MethodReturnsPurpose
get_name()stringUnique action ID used in code
get_label()stringDisplay label in editor
run($record, $ajax_handler)voidExecute on form submission
register_settings_section($widget)voidOptional: add action controls
on_export($element)arrayOptional: strip sensitive data on export

Action Controls

Always wrap in a section with submit_actions condition:

public function register_settings_section( $widget ): void {
    $widget->start_controls_section( 'section_my_action', [
        'label' => esc_html__( 'My Action', 'textdomain' ),
        'condition' => [ 'submit_actions' => $this->get_name() ],
    ]);
    $widget->add_control( 'my_api_key', [
        'label' => esc_html__( 'API Key', 'textdomain' ),
        'type' => \Elementor\Controls_Manager::TEXT,
    ]);
    $widget->end_controls_section();
}

Record Data ($record) and AJAX Handler

public function run( $record, $ajax_handler ): void {
    $settings = $record->get( 'form_settings' );    // Editor control values
    $raw_fields = $record->get( 'fields' );          // All submitted fields
    // Normalize: $fields[ $id ] = $field['value']
    $fields = [];
    foreach ( $raw_fields as $id => $field ) {
        $fields[ $id ] = $field['value'];
    }
    // AJAX handler methods:
    $ajax_handler->add_error( $field_id, 'Error message' );
    $ajax_handler->add_success_message( 'Success!' );
}

On Export -- strip sensitive settings

public function on_export( $element ): array {
    unset( $element['my_api_key'], $element['my_secret'] );
    return $element;
}

Simple Example: Webhook Ping Action

class Ping_Action_After_Submit extends \ElementorPro\Modules\Forms\Classes\Action_Base {
    public function get_name(): string { return 'ping'; }
    public function get_label(): string { return esc_html__( 'Ping', 'textdomain' ); }

    public function run( $record, $ajax_handler ): void {
        wp_remote_post( 'https://api.example.com/', [
            'headers' => [ 'Content-Type' => 'application/json' ],
            'body' => wp_json_encode([
                'site' => get_home_url(),
                'action' => 'Form submitted',
            ]),
            'timeout' => 60,
        ]);
    }

    public function register_settings_section( $widget ): void {}
    public function on_export( $element ): array { return $element; }
}

Advanced Example: Sendy Subscriber Action

class Sendy_Action_After_Submit extends \ElementorPro\Modules\Forms\Classes\Action_Base {
    public function get_name(): string { return 'sendy'; }
    public function get_label(): string { return esc_html__( 'Sendy', 'textdomain' ); }

    public function register_settings_section( $widget ): void {
        $widget->start_controls_section( 'section_sendy', [
            'label' => esc_html__( 'Sendy', 'textdomain' ),
            'condition' => [ 'submit_actions' => $this->get_name() ],
        ]);
        $widget->add_control( 'sendy_url', [
            'label' => esc_html__( 'Sendy URL', 'textdomain' ),
            'type' => \Elementor\Controls_Manager::TEXT,
            'placeholder' => 'https://your_sendy_installation/',
        ]);
        $widget->add_control( 'sendy_list', [
            'label' => esc_html__( 'Sendy List ID', 'textdomain' ),
            'type' => \Elementor\Controls_Manager::TEXT,
        ]);
        $widget->add_control( 'sendy_email_field', [
            'label' => esc_html__( 'Email Field ID', 'textdomain' ),
            'type' => \Elementor\Controls_Manager::TEXT,
        ]);
        $widget->add_control( 'sendy_name_field', [
            'label' => esc_html__( 'Name Field ID', 'textdomain' ),
            'type' => \Elementor\Controls_Manager::TEXT,
        ]);
        $widget->end_controls_section();
    }

    public function run( $record, $ajax_handler ): void {
        $settings = $record->get( 'form_settings' );
        if ( empty( $settings['sendy_url'] ) || empty( $settings['sendy_list'] ) || empty( $settings['sendy_email_field'] ) ) {
            return;
        }
        $raw_fields = $record->get( 'fields' );
        $fields = [];
        foreach ( $raw_fields as $id => $field ) { $fields[ $id ] = $field['value']; }
        if ( empty( $fields[ $settings['sendy_email_field'] ] ) ) { return; }

        $sendy_data = [
            'email' => $fields[ $settings['sendy_email_field'] ],
            'list'  => $settings['sendy_list'],
            'ipaddress' => \ElementorPro\Core\Utils::get_client_ip(),
            'referrer'  => isset( $_POST['referrer'] ) ? $_POST['referrer'] : '',
        ];
        if ( ! empty( $fields[ $settings['sendy_name_field'] ] ) ) {
            $sendy_data['name'] = $fields[ $settings['sendy_name_field'] ];
        }
        wp_remote_post( $settings['sendy_url'] . 'subscribe', [ 'body' => $sendy_data ] );
    }

    public function on_export( $element ): array {
        unset( $element['sendy_url'], $element['sendy_list'], $element['sendy_email_field'], $element['sendy_name_field'] );
        return $element;
    }
}

2. Form Fields

Custom field types. Extend \ElementorPro\Modules\Forms\Fields\Field_Base.

Registration

add_action( 'elementor_pro/forms/fields/register', function ( $form_fields_registrar ) {
    require_once __DIR__ . '/form-fields/my-field.php';
    $form_fields_registrar->register( new \My_Custom_Field() );
});

Required Methods

MethodReturnsPurpose
get_type()stringUnique field type ID
get_name()stringDisplay label in editor dropdown
render($item, $item_index, $form)voidOutput field HTML on frontend
validation($field, $record, $ajax_handler)voidOptional: validate submitted value
update_controls($widget)voidOptional: add field-specific controls
get_script_depends()arrayOptional: JS dependency handles
get_style_depends()arrayOptional: CSS dependency handles

Render -- use add_render_attribute

public function render( $item, $item_index, $form ): void {
    $form->add_render_attribute( 'input' . $item_index, [
        'type'  => 'text',
        'class' => 'elementor-field-textual',
        'placeholder' => esc_html__( 'Placeholder', 'textdomain' ),
    ]);
    echo '<input ' . $form->get_render_attribute_string( 'input' . $item_index ) . '>';
}

Access field control values from $item: $item['my-control-name'].

Field Validation

public function validation( $field, $record, $ajax_handler ): void {
    if ( empty( $field['value'] ) ) { return; }
    if ( ! preg_match( '/^[0-9]+$/', $field['value'] ) ) {
        $ajax_handler->add_error( $field['id'], esc_html__( 'Only numbers.', 'textdomain' ) );
    }
}

Field Controls (update_controls)

Inject into the form field repeater. Requires condition, tab, inner_tab, tabs_wrapper:

public function update_controls( $widget ): void {
    $elementor = \ElementorPro\Plugin::elementor();
    $control_data = $elementor->controls_manager->get_control_from_stack( $widget->get_unique_name(), 'form_fields' );
    if ( is_wp_error( $control_data ) ) { return; }

    $field_controls = [
        'my-placeholder' => [
            'name' => 'my-placeholder',
            'label' => esc_html__( 'Placeholder', 'textdomain' ),
            'type' => \Elementor\Controls_Manager::TEXT,
            'condition' => [ 'field_type' => $this->get_type() ],
            'tab'          => 'content',
            'inner_tab'    => 'form_fields_content_tab',
            'tabs_wrapper' => 'form_fields_tabs',
        ],
    ];
    $control_data['fields'] = $this->inject_field_controls( $control_data['fields'], $field_controls );
    $widget->update_control( 'form_fields', $control_data );
}

Content Template (JS Editor Preview)

Workaround for live preview. Do NOT name your method content_template() (reserved for future use):

public function __construct() {
    parent::__construct();
    add_action( 'elementor/preview/init', [ $this, 'editor_preview_footer' ] );
}
public function editor_preview_footer(): void {
    add_action( 'wp_footer', [ $this, 'content_template_script' ] );
}
public function content_template_script(): void {
    ?>
    <script>
    jQuery( document ).ready( () => {
        elementor.hooks.addFilter(
            'elementor_pro/forms/content_template/field/<?php echo $this->get_type(); ?>',
            function ( inputField, item, i ) {
                const fieldId    = `form_field_${i}`;
                const fieldClass = `elementor-field-textual elementor-field ${item.css_classes}`;
                return `<input id="${fieldId}" class="${fieldClass}" type="text">`;
            }, 10, 3
        );
    });
    </script>
    <?php
}

Field Dependencies

// Register in plugin main file
add_action( 'wp_enqueue_scripts', function () {
    wp_register_script( 'my-field-js', plugins_url( 'assets/js/field.js', __FILE__ ) );
    wp_register_style( 'my-field-css', plugins_url( 'assets/css/field.css', __FILE__ ) );
});
// Declare in field class
public function get_script_depends(): array { return [ 'my-field-js' ]; }
public function get_style_depends(): array { return [ 'my-field-css' ]; }
// Backward compat (Elementor < 3.28): also set public properties
public $depended_scripts = [ 'my-field-js' ];
public $depended_styles = [ 'my-field-css' ];

Simple Example: Local Tel Field with Pattern

class Elementor_Local_Tel_Field extends \ElementorPro\Modules\Forms\Fields\Field_Base {
    public function get_type(): string { return 'local-tel'; }
    public function get_name(): string { return esc_html__( 'Local Tel', 'textdomain' ); }

    public function render( $item, $item_index, $form ): void {
        $form->add_render_attribute( 'input' . $item_index, [
            'size' => '1', 'class' => 'elementor-field-textual',
            'pattern' => '[0-9]{3}-[0-9]{3}-[0-9]{4}',
            'title' => esc_html__( 'Format: 123-456-7890', 'textdomain' ),
        ]);
        echo '<input ' . $form->get_render_attribute_string( 'input' . $item_index ) . '>';
    }

    public function validation( $field, $record, $ajax_handler ): void {
        if ( empty( $field['value'] ) ) { return; }
        if ( preg_match( '/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/', $field['value'] ) !== 1 ) {
            $ajax_handler->add_error( $field['id'],
                esc_html__( 'Phone must be "123-456-7890" format.', 'textdomain' ) );
        }
    }

    public function __construct() {
        parent::__construct();
        add_action( 'elementor/preview/init', [ $this, 'editor_preview_footer' ] );
    }
    public function editor_preview_footer(): void { add_action( 'wp_footer', [ $this, 'content_template_script' ] ); }
    public function content_template_script(): void { ?>
        <script>
        jQuery( document ).ready( () => {
            elementor.hooks.addFilter( 'elementor_pro/forms/content_template/field/<?php echo $this->get_type(); ?>',
                function ( inputField, item, i ) {
                    return `<input id="form_field_${i}" class="elementor-field-textual elementor-field ${item.css_classes}" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}">`;
                }, 10, 3 );
        });
        </script>
    <?php }
}

Advanced Example: Credit Card Field with Controls and Validation

class Elementor_Credit_Card_Number_Field extends \ElementorPro\Modules\Forms\Fields\Field_Base {
    public function get_type(): string { return 'credit-card-number'; }
    public function get_name(): string { return esc_html__( 'Credit Card Number', 'textdomain' ); }

    public function render( $item, $item_index, $form ): void {
        $form->add_render_attribute( 'input' . $item_index, [
            'class' => 'elementor-field-textual', 'type' => 'tel',
            'inputmode' => 'numeric', 'maxlength' => '19',
            'pattern' => '[0-9]{4}\s[0-9]{4}\s[0-9]{4}\s[0-9]{4}',
            'placeholder' => $item['credit-card-placeholder'],
            'autocomplete' => 'cc-number',
        ]);
        echo '<input ' . $form->get_render_attribute_string( 'input' . $item_index ) . '>';
    }

    public function validation( $field, $record, $ajax_handler ): void {
        if ( empty( $field['value'] ) ) { return; }
        if ( preg_match( '/^[0-9]{4}\s[0-9]{4}\s[0-9]{4}\s[0-9]{4}$/', $field['value'] ) !== 1 ) {
            $ajax_handler->add_error( $field['id'],
                esc_html__( 'Card number must be "XXXX XXXX XXXX XXXX".', 'textdomain' ) );
        }
    }

    public function update_controls( $widget ): void {
        $elementor = \ElementorPro\Plugin::elementor();
        $control_data = $elementor->controls_manager->get_control_from_stack( $widget->get_unique_name(), 'form_fields' );
        if ( is_wp_error( $control_data ) ) { return; }
        $field_controls = [
            'credit-card-placeholder' => [
                'name' => 'credit-card-placeholder',
                'label' => esc_html__( 'Card Placeholder', 'textdomain' ),
                'type' => \Elementor\Controls_Manager::TEXT,
                'default' => 'xxxx xxxx xxxx xxxx',
                'dynamic' => [ 'active' => true ],
                'condition' => [ 'field_type' => $this->get_type() ],
                'tab' => 'content', 'inner_tab' => 'form_fields_content_tab', 'tabs_wrapper' => 'form_fields_tabs',
            ],
        ];
        $control_data['fields'] = $this->inject_field_controls( $control_data['fields'], $field_controls );
        $widget->update_control( 'form_fields', $control_data );
    }

    public function __construct() {
        parent::__construct();
        add_action( 'elementor/preview/init', [ $this, 'editor_preview_footer' ] );
    }
    public function editor_preview_footer(): void { add_action( 'wp_footer', [ $this, 'content_template_script' ] ); }
    public function content_template_script(): void { ?>
        <script>
        jQuery( document ).ready( () => {
            elementor.hooks.addFilter( 'elementor_pro/forms/content_template/field/<?php echo $this->get_type(); ?>',
                function ( inputField, item, i ) {
                    return `<input type="tel" id="form_field_${i}" class="elementor-field-textual elementor-field ${item.css_classes}" inputmode="numeric" maxlength="19" placeholder="${item['credit-card-placeholder']}" autocomplete="cc-number">`;
                }, 10, 3 );
        });
        </script>
    <?php }
}

Removing Built-in Fields

add_filter( 'elementor_pro/forms/field_types', function ( $fields ) {
    unset( $fields['upload'] ); // Remove file upload field
    return $fields;
});

3. Form Validation

Global validation hook fires before form processing:

add_action( 'elementor_pro/forms/validation', function ( $record, $ajax_handler ) {
    $fields = $record->get( 'fields' );

    // Single field validation
    if ( ! empty( $fields['my_field']['value'] ) && strlen( $fields['my_field']['value'] ) < 5 ) {
        $ajax_handler->add_error( 'my_field', esc_html__( 'Min 5 characters.', 'textdomain' ) );
    }

    // Cross-field validation
    if ( ! empty( $fields['password']['value'] ) && ! empty( $fields['confirm']['value'] ) ) {
        if ( $fields['password']['value'] !== $fields['confirm']['value'] ) {
            $ajax_handler->add_error( 'confirm', esc_html__( 'Passwords do not match.', 'textdomain' ) );
        }
    }
}, 10, 2 );

Any add_error() call halts submission and returns errors to the client.


4. Form Processing Hooks

HookParamsWhen
elementor_pro/forms/validation$record, $ajax_handlerBefore processing -- validate fields
elementor_pro/forms/process$record, $ajax_handlerDuring form processing
elementor_pro/forms/new_record$record, $ajax_handlerAfter successful submission
elementor_pro/forms/mail_sent$settings, $recordAfter email action sends

Email Filters

add_filter( 'elementor_pro/forms/wp_mail_headers', function ( $headers ) {
    return $headers . "Cc: copy@example.com\r\n";
});
add_filter( 'elementor_pro/forms/wp_mail_message', function ( $message ) {
    return $message . "\n\n-- Sent via My Site";
});

Webhook Filter

add_filter( 'elementor_pro/forms/webhooks/response', function ( $response, $record ) {
    if ( is_wp_error( $response ) ) {
        error_log( 'Webhook failed: ' . $response->get_error_message() );
    }
    return $response;
}, 10, 2 );

5. Common Mistakes

MistakeFix
Missing condition on action controls sectionSet 'condition' => ['submit_actions' => $this->get_name()]
Hardcoding HTML attributes in render()Use $form->add_render_attribute() / get_render_attribute_string()
Not checking empty($field['value']) in validationAlways return early if empty (required check is separate)
Naming a method content_template() on field classReserved for future use -- use content_template_script() workaround
Exporting sensitive control dataImplement on_export() with unset() for all sensitive keys
Not escaping labels and attributesUse esc_html__() for labels, esc_attr() for attributes
Missing is_wp_error() check in update_controls()Always guard get_control_from_stack() result
Missing tab/inner_tab/tabs_wrapper on field controlsRequired for controls to appear in the correct repeater tab
Wrong registration hookActions: elementor_pro/forms/actions/register. Fields: elementor_pro/forms/fields/register
Not calling parent::__construct() in field constructorRequired when overriding __construct() for editor preview

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

35.43%
按下载量换算35

Claude

33.2%
按下载量换算33

Cursor

18.53%
按下载量换算18

Gemini CLI

10.29%
按下载量换算10

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills