Creating a new field type

Last updated Jan 16, 2024

Overview

The Advanced Custom Fields plugin is packed with loads of useful field types such as text, image and WYSIWYG. However, when working on a project, it may be necessary to create a new type of field to save & load unique data.

This guide will demonstrate how to create a new field type for the ACF plugin.

Download

To make life easier, we put together a comprehensive template for creating an ACF field type, complete with an NPM script that get you up and running even faster.

A screenshot of the ACF Example Field Type repository

ACF Example Field Type template on Github

Please download or clone the ACF Example Field Type repository. Alternatively, you can click the green “Use this template” button to create a new repository based on this template.

https://github.com/AdvancedCustomFields/acf-example-field-type

Once you’ve downloaded the template, follow the steps in the README to get started on your custom field type.

Customization

All logic for your field’s appearance and functionality is defined in the acf-FIELD-NAME/class-PREFIX-acf-field-FIELD-NAME.php file. This class extends the acf_field class, which is packed full of powerful functions which allow you to customize how data is saved and displayed! Each function is documented with internal comments, so it is best to open up the file and read it over top to bottom.

Here is a quick overview of the functions:

Name Description
__construct Initialize function which sets the field’s data such as name, label, category and defaults
render_field_settings Create extra settings for your field. These are visible when editing a field
render_field Create the HTML interface for your field
input_admin_enqueue_scripts Enqueue CSS + JavaScript to assist your render_field() function
input_admin_head Add inline CSS and JavaScript to assist your render_field() function
input_form_data Add hidden inline HTML
input_admin_footer Add inline CSS and JavaScript to assist your render_field() function
load_value This filter is applied to the $value after it is loaded from the db
update_value This filter is applied to the $value before it is saved in the db
format_value This filter is applied to the $value before being returned to template API
validate_value This filter is used to perform validation on the value prior to saving
delete_value This action is fired after a value has been deleted from the db

The above are only some of the functions available in the acf_field class. Please read over the extended comments found above each function to learn more.

HTML Escaping

Some field types may output potentially unsafe HTML directly, such as iframes or script tags.

Starting from ACF 6.2.5, where these would automatically be removed when using the ACF shortcode or the_field(), ACF supports field types escaping their own HTML when requested. This is done by a second parameter being passed into the format_value method, if this value is true, we require a HTML safe version of the output.

In this instance, your field type should ensure there is no way for malicious HTML to be rendered on the front-end by a malicious user modifying the raw value in the database. For example, the core WYSIWYG field handles this by running acf_esc_html on the value before running the_content filter to handle any embeds in the field.

Once your field type is ready to handle its own HTML, you can mark the field as compatible by adding ’escaping_html’ => true to the new supports class property:

$this->supports = array(
    'escaping_html' => true,
);
Supercharge Your Website With Premium Features Using ACF PRO

Speed up your workflow and unlock features to better develop websites using ACF Blocks and Options Pages, with the Flexible Content, Repeater, Clone, Gallery Fields & More.

Explore Features View Pricing

PRO Features
ACF Blocks
Options Pages
PRO Fields
Repeater
Flexible Content
Gallery
Clone
', { 'class': notice_class } ); var $coupon_message = $( '

', { 'class': 'dbrains-wc-coupons-notice-message' } ); $coupon_message.html( message ); $coupon_notice.prepend( $coupon_message ) $( 'body' ).prepend( $coupon_notice ); var coupon_height = $coupon_notice.outerHeight(); $coupon_notice .css( 'margin-top', - 1 * coupon_height ) .show() .animate( { 'margin-top': 0 }, 800 ); setTimeout( function() { $coupon_notice .animate( { 'margin-top': - 1 * coupon_height }, 800, function() { $( this ).remove(); } ); }, 4000 ); // clear the cookies BRAINS_ALERT_BAR.delete_cookie( cookie_name, { path: '/' } ); BRAINS_ALERT_BAR.delete_cookie( cookie_name_error, { path: '/' } ); } }; jQuery( document ).ready( function( $ ) { BRAINS_ALERT_BAR.setup_url_coupons( $ ); } );