Click to initialize TinyMCE
You can register a form in the “ACF > Forms” menu or using acfe_register_form() as below. See Settings Cheatsheet for the list of all available arguments.
Usage example:
add_action('acfe/init', 'my_form_register');
function my_form_register(){
acfe_register_form(array(
'name' => 'my-form',
'title' => 'My Form',
'field_groups' => array(
'group_5ffd27b7d0c62',
),
'attributes' => array(
'submit' => array(
'value' => 'Submit Form',
),
),
'success' => array(
'message' => 'The page "{action:post:post_title}" has been created.',
),
'actions' => array(
array(
'action' => 'post',
'type' => 'insert_post',
'save' => array(
'post_type' => 'page',
'post_status' => 'publish',
'post_title' => '{field:field_5ff7ee7cdd8f3}',
'acf_fields' => array(
'field_6102a25520748',
'field_63efcca4ea9b8',
),
),
),
),
));
}#Render with form name
Once registered, the form can be rendered anywhere on the front-end using the acfe_form() function, with the form name as argument:
<?php get_header(); ?>
<?php acfe_form('my-form'); ?>
<?php get_footer(); ?>#Render with form id
Alternatively, you can use the form ID, in case the form was registered with the Form UI:
<?php get_header(); ?>
<?php acfe_form(120); ?>
<?php get_footer(); ?>#Render and override settings
You can also render a form and override settings on the fly. To do so, pass an array with a name or ID to choose which form to display, and override existing settings. Usage example:
<?php get_header(); ?>
<?php
acfe_form(array(
'name' => 'my-form', // render 'my-form'
'success' => array(
'message' => 'Success!', // change the success message
),
));
?>
<?php get_footer(); ?>Alternatively, it is possible to register and render an inline form, directly within the front-end template. The following form doesn’t require acfe_register_form(), as it is created and displayed on the fly:
<?php get_header(); ?>
<?php
// create & render an inline form
acfe_form(array(
'name' => 'inline-form',
'title' => 'Inline Form',
'field_groups' => array(
'group_5ffd27b7d0c62',
),
'attributes' => array(
'submit' => array(
'value' => 'Submit',
),
),
'success' => array(
'message' => 'The page "{action:post:post_title}" has been created.',
),
'actions' => array(
array(
'action' => 'post',
'type' => 'insert_post',
'save' => array(
'post_type' => 'page',
'post_status' => 'publish',
'post_title' => '{field:field_5ff7ee7cdd8f3}',
'acf_fields' => array(
'field_6102a25520748',
'field_63efcca4ea9b8',
),
),
),
),
));
?>
<?php get_footer(); ?>The most basic way to display field groups is to fill the field_groups argument. The form will automatically display the related fields.
acfe_form(array(
'name' => 'my-form',
'field_groups' => array(
'group_5ffd27b7d0c62',
'group_5ffd66b8aa7ca',
),
));If you need to control where the fields are displayed you can use it in combination with the render argument, and the {render:fields} template tag.
The following example will render both field groups within arbitrary HTML:
acfe_form(array(
'name' => 'my-form',
'field_groups' => array(
'group_5ffd27b7d0c62',
'group_5ffd66b8aa7ca',
),
'render' => '
<h3>My Form</h3>
<div class="wrapper">
{render:fields}
</div>
',
));As an alternative, it is possible to omit the field_groups argument, and directly use {render:group_5f5e3b3b1b1d1}. The following example will split the displayed field groups:
acfe_form(array(
'name' => 'my-form',
'render' => '
<h3>Field Group 1</h3>
<div class="wrapper">
{render:group_5ffd27b7d0c62}
</div>
<h3>Field Group 2</h3>
<div class="wrapper">
{render:group_5ffd66b8aa7ca}
</div>
',
));It is also possible to render each fields individually, using the field name or key. Please note that you can only render top-level fields.
For example, you cannot render Repeater sub fields individually, you have to render the whole repeater. If you need to hide a sub field, please see the Hide Field section.
acfe_form(array(
'name' => 'my-form',
'render' => '
<div class="row">
<div class="col-6">
{render:my_field}
</div>
<div class="col-6">
{render:field_5ffa85c208d1e}
</div>
<div class="col-12">
{render:field_5ff29c5ba9df9}
</div>
</div>
',
));The submission button is rendered after all the fields by default, but it can be also placed manually with the {render:submit} tag. Note the submit attribute must still be enabled and filled.
acfe_form(array(
'name' => 'my-form',
'render' => '
<h3>My Form</h3>
<div class="wrapper">
{render:submit}
{render:field_5ff7ee7cdd8f3}
{render:field_5ffa85c208d1e}
</div>
',
));Fields can be prefilled with values using the map argument. Assigned values must be unformatted and compatible with their field type. For example, a Date Picker field value should use the YYYYMMDD format.
acfe_form(array(
'name' => 'my-form',
'render' => '
{render:field_5ff7ee7cdd8f3}
{render:field_5ffa85c208d1e}
',
'map' => array(
'field_5ff7ee7cdd8f3' => array(
'value' => 'my value',
),
'field_5ffa85c208d1e' => array(
'value' => 'my other value',
),
),
));Here is an example with a more complex field, like a Repeater:
acfe_form(array(
'name' => 'my-form',
'render' => '
{render:field_5ff7ee7cdd8f3}
',
'map' => array(
// repeater field
'field_5ff7ee7cdd8f3' => array(
'value' => array(
array(
'field_621a65cc5521e' => 'Row 1',
),
array(
'field_621a65cc5521e' => 'Row 2',
),
)
),
),
));If you need to inject values from existing fields in the database, make sure to get unformatted values. To do so, add false as the last argument in your get_field(). See documentation.
// get value from existing post (unformatted)
$my_field = get_field('my_field', 145, false);
acfe_form(array(
'name' => 'my-form',
'render' => '
{render:field_5ff7ee7cdd8f3}
',
'map' => array(
'field_5ff7ee7cdd8f3' => array(
'value' => $my_field, // use value
),
),
));The map argument allows to hide specific fields by assigning false, just like in the acf/prepare_field hook.
acfe_form(array(
'name' => 'my-form',
'render' => '
{render:group_5ffd27b7d0c62}
',
'map' => array(
'field_5ff7ee7cdd8f3' => false, // hide this field
),
));Following this logic, we can also change the label, instructions and other field settings:
acfe_form(array(
'name' => 'my-form',
'render' => '
{render:field_5ff7ee7cdd8f3}
',
'map' => array(
'field_5ff7ee7cdd8f3' => array(
'label' => 'New Label',
'instructions' => 'New Instructions',
// ...
),
),
));The easiest way to validate the whole form is to use the acfe/form/validate_form hook. You can retrieve any field input value using get_field() and omit the $post_id argument.
To throw an error, simply use the acfe_add_validation_error() helper.
add_action('acfe/form/validate_form/form=my-form', 'my_form_validation');
function my_form_validation($form){
// get field input value
$my_field = get_field('my_field');
// get field input value (unformatted)
// $my_field = get_field('my_field', false, false);
// check field value
if($my_field === 'my value'){
// add validation error
acfe_add_validation_error('my_field', 'my value is not allowed');
}
}Indeed, the native ACF hook acf/validate_value will also work for front-end forms. However, you have to make sure the request comes from the front-end, and not the WP Admin, using acfe_is_front().
add_filter('acf/validate_value/name=my_field', 'my_acf_validate_value', 10, 4);
function my_acf_validate_value($valid, $value, $field, $input_name){
// bail early if not on the front-end
if(!acfe_is_front()){
return $valid;
}
// ...
return $valid;
}Following the same logic as the validation, you can retrieve field input values with get_field() inside the acfe/form/submit_form hook. See documentation.
In this example, we’ll create a new page using fields values, and update ACF fields in the new page with update_field().
<?php get_header(); ?>
<?php
acfe_form(array(
'name' => 'my-form',
'title' => 'My Form',
'field_groups' => array(
'group_5ffd27b7d0c62',
),
));
?>
<?php get_footer(); ?>add_action('acfe/form/submit_form/form=my-form', 'my_form_submission');
function my_form_submission($form){
// get title input value
$title = get_field('title');
// get description input value
$description = get_field('description');
// create page
$post_id = wp_insert_post(array(
'post_title' => $title, // use title field
'post_content' => $description, // use description field
'post_type' => 'page',
'post_status' => 'publish',
));
// make sure the page was created
if($post_id && !is_wp_error($post_id)){
// get fields input value
// we must get unformatted values in order to update fields later
$date = get_field('date', false, false);
$checkbox = get_field('checkbox', false, false);
// update acf fields on the new page
update_field('date', $date, $post_id);
update_field('checkbox', $checkbox, $post_id);
}
}The exact same result can be achieved using the built-in Post Action, with less code. Usage example:
<?php get_header(); ?>
<?php
acfe_form(array(
'name' => 'my-form',
'title' => 'My Form',
'field_groups' => array(
'group_5ffd27b7d0c62', // display field group
),
'actions' => array(
array(
'action' => 'post',
'type' => 'insert_post',
'save' => array(
'post_type' => 'page',
'post_status' => 'publish',
'post_title' => '{field:field_5ff7ee7cdd8f3}', // title field
'post_content' => '{field:field_621a65cc5521e}', // description field
'acf_fields' => array(
'field_6102a25520748', // date field
'field_63efcca4ea9b8', // checkbox field
),
),
),
),
));
?>
<?php get_footer(); ?>The easiest way to control whenever a form should be rendered is to use the classic if() conditional logic.
// only display the form to logged user
if(is_user_logged_in()){
acfe_form('my-form');
}Alternatively, you can use the acfe/form/load_form hook, check your condition and return false to hide the form. This example will achieve the same result, but without the if() condition on the front-end template.
add_filter('acfe/form/load_form/form=my-form', 'my_form_load');
function my_form_load($form){
// check if user is logged in
if(!is_user_logged_in()){
return false; // hide form
}
// display form
return $form;
}<?php get_header(); ?>
<?php acfe_form('my-form'); ?>
<?php get_footer(); ?>You can pass custom data to the form during the form render, and retrieve it later in the Form UI or in PHP hooks. Usage example:
acfe_form(array(
'name' => 'my-form',
'profile_id' => get_current_user_id(), // add custom data
'actions' => array(
array(
'action' => 'redirect',
'url' => '/profile?id={form:profile_id}', // retrieve custom data
),
),
));Custom data can also be passed with the acfe/form/load_form filter. See documentation. Usage example:
add_filter('acfe/form/load_form/form=my-form', 'my_form_settings');
function my_form_settings($form){
// add custom data
$form['profile_id'] = get_current_user_id();
// return
return $form;
}These custom data can then be retrieved in any front-end forms hooks within the $form argument. Usage example:
// form submission
add_action('acfe/form/submit_form/form=my-form', 'my_form_submit');
function my_form_submit($form){
// retrieve custom data
$user_id = $form['profile_id'];
// ...
}Or directly within the Form UI using the {form:profile_id} template tag. Usage example: