This is a continuation of front end posting with ACF Pro to allow editing of posts on the front end. We will use acf_form() for the post fields, and use Sidr for the slide out menu to hold our form.
There’s a video of the final outcome at the end of this post.
I’m using a custom Genesis child theme, but you can modify the code to work however you’d like.
Let’s get started.
Add our form to blog posts
We need to load our form on single posts. We’re using the same field groups we created in the last post, and using almost the exact same code to insert the forms.
Our setup function checks to make sure a user is logged in, and is the author of the post. Naturally, we don’t want to allow anyone but the post author to edit the post. If the conditions are met, we run our functions and load our code.
Here is the full single.php:
Remember to swap out the correct ACF field keys for your custom fields, otherwise we won’t know what to do with the field input data.
We use an important ACF filter to make this work properly. It’s called acf/load_value. This filter takes our empty ACF fields and pre-loads the post content from the current post so we are able to edit and save our changes.
The code is well documented, so go through it and make sure you understand what’s happening. Again, make sure you have the correct field keys!
Also, notice the tsm_do_acf_form_content() function that contains the acf_form() code. We wrap the entire form in a div with an ID of #edit-post. This ID is what we use in our Sidr javascript later on so our #edit-toggle button knows what content to load in the slide menu.
On to the next…
Setup Sidr
First, go to the Sidr website and download the most recent version (1.2.1 at the time of this post). I am only using the Sidr js file since the CSS we need is very minimal and we can include it directly in our theme.
Next, put jquery.sidr.min.js in your child theme directory.
I put mine in: /wp-content/themes/child-theme-name/assets/js/jquery.sidr.min.js
Lastly, create a file to trigger our slide out form. I called mine edit-post.js. Put it in the same location as the sidr file: /wp-content/themes/child-theme-name/assets/js/edit-post.js
If you change the location of these files, make sure you change the location in the tsm_acf_form_edit_post_enqueue_scripts() function above so the code knows where to find the files.
Here is the code we need to make Sidr slide in from the left, and also close when you click the ‘Close’ button that we’re going to add later on. Props to Robin Cornett for the help in dissecting Sidr.
The heavy lifting is done, now lets move on to CSS.
Make it look pretty
Remember that we didn’t load the Sidr CSS earlier. There is way more in that CSS then we really need, since we aren’t using an actual menu.
Here is the CSS I used for the slide out menu, with a few small tweaks to the ACF form itself.
There’s a lot of code here, and it might be a little overwhelming. Hopefully you already have a decent knowledge of ACF, because once you get the hang of acf_form() it’s a super powerful tool…
See it all in action here:
Happy coding ๐
Nik Alex says
Hey! I am trying for hours to make this work but no luck ๐ Here is what i did:
1. I created a php file and named it front_end_edit.php. I pasted in there this: https://gist.github.com/JiveDig/4f5294f35b3bb79961e1#file-acf_front_end_edit-php
2. Then i downloaded the jquery.sidr.min.js and added to my themes directory.
3. I created the edit-post.js and pasted in there this: https://gist.github.com/JiveDig/32fab145a95c3ce0a546#file-sidr_edit_post-js
I have no idea how to add the edit button in my page. Please help me. Thank you.
JiveDig says
Hey Nik, sorry you’re having trouble… this is quite an advanced tutorial for sure.
You shouldn’t be using front_end_edit.php unless you are making that file a page template. I have my code in single.php so it automatically runs on single posts. Check out the WordPress template hierarchy if you’re not familiar with it already.
The “edit” button is already in my single.php code example above. It’s this function:
/**
* Add edit post toggle button
*/
add_action( 'genesis_entry_header', 'tsm_do_acf_form_edit_toggle', 5 );
Nik Alex says
Three days ago i discovered php and before two days i found advanced custom fields! I thought it would be easier! I tried for hours to make it work but no luck ๐ Thank you for your reply. Stay awesome ๐
Gio says
Hi,
great tutorial, after a while I’ve been able to setup everything.
I have a question: I have added a field to allow users upload a file (pdf) from the frontend, and now I’m trying to output the url of that file on the frontend (like your repeater field), but I dont know how to achieve this.
I’ve added a line of code both in the
page_template
and insingle.php
in my child theme:'file_progetto' => $_POST['acf']['field_553d0187c00cb'], // Upload file ACF field key
and now i’m able to upload the file and when i edit the post i see the file in the edit section, I can edid/update/delete, but I can’t figure out how to have it showing on the frontend. Can you give a little help on this?Thanks a lot!
๐
JiveDig says
No prob. That’s just standard ACF stuff there… checkout the snippets here http://www.advancedcustomfields.com/resources/file/
It mostly depends how you have the return value set in your field settings.
Gio says
Hi,
got it!
if( get_field('file_progetto') ):
?><a href="" >Download File<?php
endif;
This snippet worked like a charm!
ACF is so powerfull! And Genesis is a grat framework! I think I need to deepen my knowledge on these tools.
Thanks again.
Gio
josh says
First off, absolutely great tutorial. Really appreciated you saved me countless hours.
A quick question for anyone who may know:
Once the “close” button is pressed in the flyout edit form, the page reloads and the form is saved. I would like this to act as a “cancel” button instead, with no page reload or form submission – i.e. leave that for the “submit” button.
I’ve tried and can’t seem to figure it out, thanks in advance!
,JiveDig says
Hey Josh. That same issue stumped me for a bit. Turns out that the button element by default forces a page refresh. Try changing that to an anchor link. Close or similar. That’s typed from my phone so just giving an idea. That shouldn’t force a refresh.
Josh says
Thanks, I decided not to use the flyout after all but I remember the solution was something like what you mentioned.
Toon says
Changing from a button element to an anchor link also forces a refresh.
Just put it in a or and style it via CSS to make it look like a button, like this:
.sidr .edit-close {
display: block;
margin-bottom: 10px;
margin-top: 10px;
background-color: red;
border: 1px solid red;
padding: 10px;
text-align: center;
color: #fff;
cursor: pointer;
width: 200px;
}
.sidr .edit-close:hover {
background-color: #fff;
color: red;
}
Toon says
Hmm,
something went wrong when posting..
This line: Just put it in a or and style it etc.
Should read: Just put it in a ‘p’ or ‘span’ and style it etc.
josh says
Hey guys, just an update the solution was simple:
Just move this line
Close
out of: ‘html_before_fields’
and place directly under:
JiveDig says
Interesting. That worked? I’ll have to check it out.
Ben says
Yep, that seems to work well. Josh’s comment got stripped out, but if you take the whole div class ‘edit-close-wrap’ out of the ‘html_after_fields’ section and paste it immediately after div id=”edit-post” then it will close the sidr panel without saving the page and refreshing.
Rajyaguru says
I have twentytheen theme… i want above work on my side…
I am going to hire…
Here is link of sider which i want for my custom fields : http://www.berriart.com/sidr/
Here is link of Resource to follow : http://thestizmedia.com/front-end-post-editing-with-acf-pro/ (See this link what i want same like this)
WordPress CMS
Plugins : Advance Custom Fields pro v.5 (Latest)
I have knowledge of custom field use AFC but i do not know about jquery.
I want this project on http://www.Nocholk.com
Rajyaguru says
Anyone can work for me on price?
Rj says
@Rajyaguru Still needing help?
Rudi says
It seems like the title gets cleared and the author overwritten when saving? Is there a way around this?
JiveDig says
I’ve not seen this issue.
When you edit a post, it pre-loads the form with the existing content then overwrites (re-saves) all fields when you save again. The title shouldn’t get cleared though, just re-saved with whatever value is in the title field.
Alex Durston says
Hi Mike, great post, I have just implemented this into a custom theme we are working on. The only slight mod I made was to reaplce $post_id = wp_insert_post( $post ); with $post_id = wp_update_post( $post and then removed the post status arg as I wanted to retain the current post status. This is useful as we allow posts to be created and edited but they only get published once they have been paid for. Thanks for posting the article!
JiveDig says
Good stuff Alex! Glad it helped you.
Denis says
Hi Mike,
nice tutorial. Is there a way to create a frontend dashboard of all posts a user created?
And then a link to the ACF edit frontend form?
Thanks an happy new year,
Denis
JiveDig says
There’s always a way! That’s a total custom job though, and way too much for comments. I’d probably make a pseudo-menu that uses query parameters for each dashboard page, and swap out the content that way.
Josh says
Hey Mike,
Is this code still working? My fields suddenly stopped saving entirely, wondering if you’re experiencing the same. Likely not but just wanted to make sure. Thanks
Josh says
I figured out the problem – it is actually being caused by jquery/css strangely enough. My edit form is in a tab instead of slide-out and having it set to “display: none;” on load caused issues.
I’d recommend updating your code though, ACF has a much simpler way of handling the front-end forms now:
http://www.advancedcustomfields.com/resources/create-a-front-end-form/
cheers
JiveDig says
Hey Josh, thanks for stopping by!
The code you linked to won’t work for Genesis, that’s why mine looks so different. Also, I handle the acf_form() arguments manually, to have more control. If the default setup works for you, then you certainly don’t need all the extra (manual processing) code. Either way, glad you got it working!
Josh says
Thanks for the reply Mike. I think the custom post title etc. saved to post is the key difference? But for example do you have to load the content etc. with a function every time?
Starting out, it was very tricky for me to follow the code up there to get it to work. It was all worth it and a great resource – but in the end it turned out I could just use the simple function provided by ACF – I just didn’t know about the genesis hooks, which are also simple but not so to someone starting out.
Here’s an example of what I mean, a form that will edit the post but is very short. For beginners out there just wanting to have a front-end form for custom fields with genesis, it may be worth introducing at least this simple concept. Cheers! Hope it helps someone
//Add ACF form head to header using genesis hook "get_header"
add_action( 'get_header', 'acf_form_head', 1);
//Create a function to add acf form to chosen hook
function function_name() {
echo '';
$options = array(
'field_groups' => array('$group_id'),
'form' => true,
'return' => '%post_url%',
/*'html_before_fields' => ''*/
'html_after_fields' => '',
'submit_value' => __('Save', 'acf'),
);
acf_form( $options );
echo '';
}
//Add acf form to page using a genesis hook --> choose one from this guide http://genesistutorials.com/visual-hook-guide/
add_action( 'genesis_hook', 'function_name' );
JacquesMivi says
Hello,
Thanks a lot for you work, and share. I success to create a front page form with your help, but I got some troubles on edit front form.
I can’t use ajax sidebar, so I create a new template where I catch a specific post.
But when I try to use action in my custom loop, nothing appear, have you an idea ?
ID == $post->post_author ) ) {
// return;
}*/
remove_action (‘genesis_loop’, ‘genesis_do_loop’); // Remove the standard loop
add_action( ‘genesis_loop’, ‘custom_front_edit_single_loop’ ); // Add custom loop
function custom_front_edit_single_loop() {
echo ‘ id : ‘. $_GET[‘post’];
$loop = get_post($_GET[‘post’]);
$args = array(
‘p’ => $_GET[‘post’], // Get the post ID
‘post_type’ => ‘espresso_events’, // Your post type ( post, page, custom post type )
);
$loop = new WP_Query( $args );
if( $loop->have_posts() ):
while( $loop->have_posts() ): $loop->the_post();
global $post;
echo get_the_title(); // works
// Add required acf_form_head() function to head of page
add_action( ‘get_header’, ‘tsm_do_acf_form_head’, 1 );
// Deregister the admin styles outputted when using acf_form
add_action( ‘wp_print_styles’, ‘tsm_deregister_admin_styles’, 999 );
// Add the acf_form
add_action( ‘genesis_entry_content’, ‘tsm_do_acf_form_content’ );
// Load existing informations
//add_filter( ‘acf/load_value/key=field_54dfc93e35ec4’, ‘tsm_load_post_title’, 10, 3 );
add_filter( ‘acf/load_value/key=field_54dfccb977a11’, ‘tsm_load_post_category’, 10, 3 );
add_filter( ‘acf/load_value/key=field_54dfcd4278d63’, ‘tsm_load_post_thumbnail’, 10, 3 );
add_filter( ‘acf/load_value/key=field_54dfc94e35ec5’, ‘tsm_load_post_content’, 10, 3 );
add_filter( ‘acf/load_value/key=field_56a2c6ca59e98’, ‘tsm_load_post_venue’, 10, 3 );
add_filter( ‘acf/load_value/key=field_56a50a57dba0a’, ‘tsm_load_post_formateur1’, 10, 3 );
add_filter( ‘acf/load_value/key=field_56a511a4e331e’, ‘tsm_load_post_formateur2’, 10, 3 );
add_filter( ‘acf/load_value/key=field_56a511eac8f0f’, ‘tsm_load_post_organizer1’, 10, 3 );
// Update existing post data
add_action( ‘acf/save_post’, ‘tsm_update_existing_post_data’, 10 );
endwhile;
}
function tsm_do_acf_form_head() {
acf_form_head();
}
function tsm_deregister_admin_styles() {
wp_deregister_style( ‘wp-admin’ );
}
function tsm_do_acf_form_content($post_id) {
$edit_post = array(
‘post_id’ => $post->ID, // Get the post ID
‘field_groups’ => array(‘group_54dfc93792c38’, ‘group_569a815405075’), // Create post field group ID(s)
‘form’ => true,
‘return’ => ‘%post_url%’, // Redirect to new post url
‘html_before_fields’ => ”,
‘html_after_fields’ => ”,
‘submit_value’ => ‘Poster’,
‘updated_message’ => ‘Saved!’
);
acf_form( $edit_post );
}
function tsm_update_existing_post_data( $post_id ) {
// Update existing post
$post = array(
‘post_id’ => $post_id, // Get the post ID
‘post_type’ => ‘espresso_events’, // Your post type ( post, page, custom post type )
‘post_status’ => ‘publish’, // (publish, draft, private, etc.)
‘post_title’ => $_POST[‘acf’][‘field_54dfc93e35ec4’], // Post Title ACF field key
‘post_content’ => $_POST[‘acf’][‘field_54dfc94e35ec5’], // Post Content ACF field key
);
// Update the post
$post_id = wp_update_post( $post );
return $post_id;
}
/* Some Getter – Works */
genesis();
Toon van der Struijk says
I’ve got 1 question:
Where does the number ’58’ come from on line 106 in the PHP file?
And some additions for those who like to use this (and the PHP code from part 1) as a specific Page template:
When you create a page (part 1 of this tutorial), don’t forget to add ”page_template’ => ‘your-template.php,’ in the array at line 71, and also change ‘post_type’ to ‘page’. The ‘your-template.php’ contains the code from the PHP file above.
And if you edit a page, don’t forget to add ”post_type’ => ‘page’, in the above PHP template. Otherwise your changes will be saved to a post, even if it was a page (the original page will automagically disappear if you don’t change the post_type).
JiveDig says
Hi Toon, there are a few ways to get the group ID. I usually use an /acf-json/ directory in my child theme, so I just look in the correct JSON file there to get it. Thanks for stopping by!
A Serial Thinker says
Hey, I am using your solution for a new website I am working on, but using a custom_post_type instead. I had two issues:
the editing panel was empty: I solved changing __ to __ in function tsm_do_acf_form_content().when changing anything on the post, it would be “migrated” from custom post type, to “post” type: solved adding
'post_type' => 'project',
to $post array in tsm_update_existing_post_data.Cheers
A Serial Thinker says
Hmmm the code got stripped and I cannot edit the comment…
JiveDig says
Strange. Glad you got it working though!
Ali says
I am stuck in the same isssue. CAn you please help me by posting complete solution for this issue.
ugur says
Hello,
Thanks for your great tutorial.
I am using Genesis Agentpress Pro child theme with Agentpress Listings plugin.
There is any problem for Front End posting. I can add listings but I can’t editing them on Front End.
I added your single.php to my child theme directory. All fields in single.php are true. I created also javascript files.
I can see Edit link on listings. When I try to click Edit link, sidr is working fine but edit area is empy.
What is the problem?
I’m so sorry for my bad English. I hope you understand me.
Thanks,
JiveDig says
Sounds like you may have the wrong field group ID’s? So many factors in the code here, it’s hard to really say what the problem is.
neil says
Make sure you are using sidr 1.2 – otherwise pull out screen will be blank
JiveDig says
Hey Neil, if you use the latest Sidr just remove the display:none; inline style from the wrapping element HTML. I’ll update the post when I get a minute.
neil says
ok great – yes see that now and removed the style – have used the newer Sidr – all good
Angelo says
Hi Jive, can you do this in my site o give an especial guide , I will pay for it ..let me explain. I would like to do a frontend post for Listings in the genesis child theme AgentPress Pro , Im not gonna use this for properties, i will used for some kind of service sumition,I will use Agent Press becouse i like the filter search of the theme and plugin
seb says
Just saw recently that everything is working exept the conditional logic, all get displayed in the front end of the script. It uses to work fine, but seem to have broken lately, tried disable all other plugins but it dosen’t seem to change anything. Do you have a idea of what it could be? Thank you
Omid says
Hi JiveDig,
I am not a developer, but I followed your steps and could finally implement your great tutorial, however I need someone help me for fine tuning, my request may seems silly, but could you help me on hourly basis please?
Thanks,
Omid
Solomon Closson says
ACF fields are just saved as regular wordpress post meta. While this is good if you need the functionality of ACF on the front-end (repeater, etc.). This makes no sense if you just need to update the fields (like text fields). It would simple be easier to just use get_post_meta($post_id, {acf_field_name}, true); and update_post_meta($post_id, {acf_field_name}, $value);
Thanks for providing an alternative, but this seems like too much work to provide for simple post meta data that, imo, should just be performed with wordpress built-in functions since that is what acf uses anyways.
JiveDig says
Thanks for stopping by Solomon. I’m not following your logic here? I use get/update_post_meta() all the time, but that has nothing to do with building a front end form to create a post. I use update_post_meta in the code to save the featured image as well. Using get_post_meta to update a field value is fine for a manual form, but unnecessary if using acf_form() since it loads the meta values for you already.
I do agree, that ACF for front end forms is not simple/easy/fast, but it’s a great option for complex forms especially when you’ll be using ACF for meta fields in the backend as well. Cheers!
Al-Mamun Talukder says
Hi JiveDig,
Since this is exclusively written for genesis framework, I wanted to share my article where I shared non-genesis code for this. Let me know what you think. ๐
https://itsmereal.com/frontend-post-submission-edit-advanced-custom-fields/
Thank you
Mark says
Have github repository?
JiveDig says
Each time I do this it gets quite custom, so I don’t currently have a single plugin/solution.
John Romaine says
Can this allow editing by anyone to any post? To suit say, a contributor style site?
JiveDig says
Right now it’s restricted to logged in users that are already the author of the post. You can change those restrictions to whatever you’d like though.
Torrento Kage says
Fatal error: Call to undefined function genesis() >> Can you please solve this
If possible Can you please share the working demo with Source code
JiveDig says
As noted in the tutorial, this code is used in a Genesis child theme. You’ll have to modify it to use outside of Genesis. Remove the `genesis();` and deal with the other Genesis-specific hooks I have in the code examples and you should be good to go.
Alfonso says
Hi Mike,
thanks a lot for this great post. There is something that I don’t understand. Why are you manually getting the fields values and updating post data if acf_form() does it all? The examples at ACF documentation for creating and editing post (or CPTs) just uses acf_form function but no post submit processing is needed. I tried removing from your code the functions to load field values and update post data and initially the post values didn’t changed but then I moved your tsm_do_acf_form_content() function outside the author checks function and it worked fine. I am not using Sidr, just showing the form in entry content. I also didn’t need to mess with field IDs and group ID. I think that this is only needed if you have multiple field groups but you don’t want to show all of them.
I am just curious about why is all this stuff needed. Maybe this was written for an old version of acf_form? Anyway, your code helped me a lot.
Thanks!