The WYSIWYG editor works just like the WP main editor. There is nothing in ACF that will let you do this and I don’t think there is anything in WP that will let you do this. If you find something that will work in the main WP editor, it will also work in the ACF field.
https://wordpress.stackexchange.com/questions/85054/how-to-add-a-class-to-ul-tags-created-by-the-wordpress-editor-tinymce/85071, the last comment is pretty much what I was thinking, having a class on the wrapper element of the ACF output rather than trying to force classes into the editor.
Whoa – after more testing, I found the validation error only happens if I try to change the parent page. I can edit other fields on the page and it validates as I expect it to.
I also found the same issue on another site on a WooCommerce product. The validation error happens on a required, but hidden and empty WYSIWYG field, and only when changing the Product Category. I can make changes to other fields and the product validates, even with the hidden, empty, required field.
I got it working using the Wysiwyg Editor to upload the image instead. Thanks for your help.
The final code is
add_action('woocommerce_single_product_summary','finish_image',22);
function finish_image() {
$terms = get_the_terms( $post->ID , 'pa_metal-finish' );
if($terms) {
foreach( $terms as $term ) {
echo '<b>Finish: </b>'. get_field('finish_img', 'pa_metal-finish'.'_'.$term->term_id);
}
}
}
With use of the Wysiwyg Editor for image upload
It too confused me at first since the filter kind of sounds like it’s editing the active toolbar but in the documentation of the hook it says:
Once a new toolbar is added to the list, it will then appear in the WYSIWYG field’s options when editing the field group.
So I added the code in your question and sure enough if I go back to edit the Field Group in Custom Fields there’s a new radio button on the WYSIWYG Field labeled ‘Very Simple’ and when selected will only display a toolbar with bold, italic, and underline buttons on it.
Same issue. Video will embed fine thru the default WYSIWYG editor, but using ACF oembed field fails.
The video ID does have a dash (-) in it, so I’m wondering if something is getting stripped / parsed incorrectly?
All other videos working fine with the oembed.
I have the same problem (@sheriffderek: you have another problem, this is offtopic), but I use the Timber plugin and Twig templates.
{{ module.richtext }}
… renders the content of the WYSIWYG editor w/o the p tags. How can I get the right HTML code using Twig?
Unfortunately, aside from throwing a link my way for Translate Options, I haven’t had much help from the WP Globus community. I’m actually trying to get the blue globe to show up on the ACF form in posts.php, not translate options (though I did install that plugin as well, on top of having purchased WP Globus Plus). Any help anyone can provide?
Also, their WYSIWYG editor functionality in the WP Globus Plus doesn’t seem to work. While I can switch languages and enter different text for each language, when I click save, it only saves the currently showing language and saves it as the default (English) language.
Please help with this! This is a big issue for us. As rdm mentioned above, it appears that the mce_external_plugins filter is not being run on the WYSIWYG field. Thank you for your help with this!
ACF only runs shortcodes when “the_content” hook is run, this only happens for WYSIWYG fields. See this https://www.advancedcustomfields.com/resources/acf-format_value/
That would work but it would be nicer if the message field was at least a WYSIWYG editor with the usual “Add Media” button.
It’s a year later but thought I’d post a solution – was trying to combine the wrong methods, and it’s actually a lot simpler than I’d thought. The issue was knowing how to insert the style select, but I didn’t how it was referred to in ACF arrays.
1) Find out the names of the toolbar elements for reference later on. In functions.php add the following:
add_filter( 'acf/fields/wysiwyg/toolbars' , 'my_toolbars' );
function my_toolbars( $toolbars )
{
echo '< pre >';
print_r($toolbars);
echo '< /pre >';
die;
}
2) Look at the bottom of the WP admin area and copy the array into a text file for future reference. We now know the names of the buttons.
< pre >Array
(
[Full] => Array
(
[1] => Array
(
[0] => formatselect
[1] => bold
[2] => italic
[3] => bullist
[4] => numlist
[5] => blockquote
[6] => alignleft
[7] => aligncenter
[8] => alignright
[9] => link
[10] => unlink
[12] => spellchecker
[14] => wp_adv
)
[2] => Array
(
[0] => styleselect
[1] => strikethrough
[2] => hr
[4] => removeformat
[5] => charmap
[6] => outdent
[7] => indent
[8] => undo
[9] => redo
)
[3] => Array
(
)
[4] => Array
(
)
)
[Basic] => Array
(
[1] => Array
(
[0] => bold
[1] => italic
[2] => underline
[3] => blockquote
[4] => strikethrough
[5] => bullist
[6] => numlist
[7] => alignleft
[8] => aligncenter
[9] => alignright
[10] => undo
[11] => redo
[12] => link
[13] => unlink
[14] => fullscreen
)
)
)
< /pre >
3) Remove or comment out the code above that displays the button array. Create your new custom toolbar.
add_filter( 'acf/fields/wysiwyg/toolbars' , 'custom_toolbars' );
function custom_toolbars( $toolbars )
{
// Add a new toolbar called "Custom" - only 1 row of buttons
$toolbars['Custom' ] = array();
$toolbars['Custom' ][1] = array('styleselect','bold','italic');
// return $toolbars
return $toolbars;
}
Hi,
This code works, but it counts the number of total HTML characters in the field, not the rendered number of characters (what the user sees in the visual editor).
For example, if you type the text « Hello World », it will count 11 characters. But if you put this same text in bold, it will count 28 characters, because the content of the field is actually : <strong>Hello World</strong>
.
So a better solution would be to strip the tags from the value variable before counting the number of characters, like so :
add_filter('acf/validate_value/name=wysiwyg_field_name', 'my_acf_validate_value', 10, 4);
function my_acf_validate_value( $valid, $value, $field, $input ){
// bail early if value is already invalid
if( !$valid ) {
return $valid;
}
if( strlen(strip_tags($value)) > 40 ) {
$valid = 'You can\'t enter more that 40 chars';
}
// return
return $valid;
}
Only the WYSIWYG Editor is capable of interpreting Shortcodes, else you have to echo the shortcode
$shortcode = get_field('shortcode');
echo do_shortcode(' . $shortcode . ');
Cheers
Johannes
No, no ideas here. Shortcodes should work the same in either an ACF WYSIWYG field or in the standard WP editor WYSIWYG. The function that is called to output the content for a shortcode is determined by the function.
Any update? It was actually working just fine with the current plugins we have, and literally nothing in our plugins or scripts has changed recently.
I am getting the same error even after updating plugin to latest version. The error occurs when I am using a WYSIWYG editor in a repeater field and try to show all buttons.
The add media and add form button work, but the entire wysiwyg editor does not show and looks broken on the page.
If you’re looking to auto-resize your WYSIWYG and textarea fields in ACF, I’ve made a plugin for that: https://wordpress.org/plugins/acf-autosize/
Hmm, the wysiwyg editor is really hard to grab. To your code I’ve added the following, as the above method of getting the ID of the wysiwyg did not work, and apparently, when the wysiwyg is there, the textarea is not (and vice-versa):
var $fields = $el.find('.acf-field').each(function(index, element) {
console.log('---');
var $type = $(element).data('type');
if ($type == 'group') {return;}
console.log('type:' + $type);
var $key = $(element).data('key');
var $val = $('input[name*=' +$key ).val();
if ($type == 'wysiwyg') {
console.log('looking for wysiwyg');
// does not work:
// var $id = $('[data-key="' + $key + '"].acf-input textarea').attr('id');
var $id = $(element).find('.acf-input div').attr('id');
//something similar; we have to trim the -wrap suffic and the wp- prefix:
$id = $id.replace('-wrap','');
$id = $id.replace('wp-acf','acf');
console.log('id' + $id);
$val = find_editor($id, 'get', '');
if ($val == undefined) {
console.log('no wysiwyg visible, look for textarea');
$val = $('#' + $id).val();
}
}
console.log($key);
console.log($val);
});
and then I added a function for get/set of the Tiny editor:
function find_editor($id, action, value) {
$editor = false;
for (i=0; i<tinyMCE.editors.length; i++) {
console.log(tinyMCE.editors[i].id);
if ($id == tinyMCE.editors[i].id) {
// found the right one, set and stop
$editor = tinyMCE.editors[i];
break;
}
}
console.log($editor);
if (action == 'set') {
if ($editor) {
// this is a tinyMCE function call
$editor.setContent("some value");
}
}
if (action == 'get') {
if ($editor) {
// this is a tinyMCE function call
return $editor.getContent();
}
}
}
So, this is beginning to work. I am not dealing with other inputs such as checkboxes yet.
#my-wrapper-id represents the ID you set for the field when creating it under the “Wrapper Attributes” settings.
I think by looking at your code you know that $el.find...
would find nested elements inside of the new row, but you can target many things.
You don’t need to use your ID, you could use any of the values output by ACF.
for some examples:
// get all of the acf field elements (TDs or DIVs) in the added row
$fields = $el.find('.acf-field');
// get all of the input elements in added row (i.e. <div class="acf-input ....
$fields = $el.find('.acf-input');
// get all of the textarea input fields
$fields= $el.find('div[data-type=textarea"]');
// get a specific textarea field in the row
// field_123456 represents the field key of the field
$field = $el.find['[data-key="field_123456"] .acf-input textarea'];
Loop over elements
// your could loop over each field like this
var $fields = $el.find('.acf-field').each(function(index, element) {
var $key = $(element).data('key');
switch ($key) {
case 'field_1234456':
// do something
break;
case 'field_654321':
// do something else
break;
} // end switch
});
you can go directly to the field with additional “find(s)”, but eventually you’ll need to know the field key for the ACF field, or some other specific information in order to get the value or set it, for example #my-wrapper-id
given in the example.
WYSIWYG fields are a special case. Not only do you need to target the acf field but you also need to target the tinyMCE element of that field and use tinyMCE methods to get or set the value. Tiny MCE keeps a list of all of the editors in the tinyMCE.editors
object. Each element of this object as an ID, for example tinyMCE.editors[index].id
. This ID value matches the ID value of the ACF field, which is dynamically generated for this purpose, so the only way to use it is to get it from the field. For example, in a test WYSIWYG field I just looked at the ACF field textarea looks like this
<textarea id="acf-editor-5b282e0b20cfc" class="wp-editor-area" name="acf[field_5b282dbecfe9e]" style="height:300px;"></textarea>
That ID is the ID of the editor value of the editor. You loop through this list of editors to find the one you want.
var $id = $('[data-key="field_123456"] .acf-input textarea).attr(id);
$editor = false;
for (i=0; i<tinyMCE.editors.length; i++) {
if ($id == tinyMCE.editors[i].id) {
// found the right one, set and stop
$editor = tinyMCE.editors[i];
break;
}
}
if ($editor) {
// this is a tinyMCE function call
$editor.setContent("some value");
}
I’ve probably given you more questions than answers in all this information. Custom JavaScript for ACF can be quite complex and there is very little documentation and what is there is pretty basic. We are mostly on our own in this area. The only reason I have any idea is by doing a lot of experimenting and looking a lot of HTML that is created by ACF.
HI John,
That is great, but now how do I loop through the ACF input/textarea fields within that row? In the example:
acf.add_action('append', function( $el ){
// $el will be equivalent to the new element being appended $('tr.row')
// find a specific field
var $field = $el.find('#my-wrapper-id');
// do something to $field
});
I do not understand the $el.find(‘#my-wrapper-id’);. I do not know what the ID of this new row is.
I was trying to do $el.each(‘input’) or something like that and couldn’t get this to work.
After a second or whatever, then newly-created row seems to have an ID of sizzle1529351842030 and when you create another row, the previous sizzle-row loses its ID, and so on. Where does the “sizzle” get its numeric portion (1529351842030)? Is that related to the ACF internal ID or is it just a timestamp?
So what I would like is a way to access all of the ACF inputs/text areas, buttons, selects, on that new row, as I want to populate it dynamically. Also, I am unsure how to set the contents of an ACF wysiwyg (tinymce) field.
I think I have part of it figured out, but I have reached the limits of what I know about with jQuery. I have a repeater row set up with various inputs, including a WYSIWYG editor. I would like to add a copy/paste button so I can just duplicate that row’s contents, or even go to another Post and paste a row.
So far, I have figured out how to add a copy button, and how to add a paste button (which basically creates a row).
Here is what I have so far; can someone review and help me figure out how to access each of the fields in a repeater row via Javascript?
// first make some buttons that we are adding dynamically:
var acf_paste_button = '<a class="acf-button button" id="acf_paste_row" href="#" data-event="paste-row">Paste Row</a>';
// TODO: Give the copy button a FA of acf-font icon
var acf_copy_button = '<a class="small acf_copy_row" href="#" data-event="copy-row" title="Click to copy this row">C</a>';
// global: Keep track of button-pasted state:
var acf_button_pasted = false;
// add a button to the bottom of the actions area:
$('.acf-actions').prepend(acf_paste_button);
// add some copy buttons to each row in the ACF:
$('td.acf-row-handle').append(acf_copy_button)
//when you click the paste row button, send a click to the "add row" button
$('body').on('click','#acf_paste_row', function() {
$('.acf-button.button.button-primary').click();
acf_button_pasted = true;
});
// when you click the coyp row, put it into a cookie
$('body').on('click','.acf_copy_row', function() {
alert('todo: COPY the inputs of this row into a cookie');
});
// listen for pasting events:
acf.add_action('append', function( $el ){
// $el will be equivalent to the new element being appended $('tr.row')
if ( acf_button_pasted ) {
// so we just added a row; now we need to add a copy button for it:
$el.find('td.acf-row-handle').append(acf_copy_button);
// find a specific field
console.log($el);
var $field = $el.find('#my-wrapper-id');
var $field = $el.find('.acf-row');
console.log($field);
console.log('now it is time to paste the stuff');
// set the flag back to false in case you want to paste again.
acf_button_pasted = false;
// .acf-input-wrap
// do something to $field
// TODO: Paste values into each of the inputs.
$el.find('input').val('fish');
// how to access a WYSIWYG editor?
//tinymce.activeEditor.execCommand('mceInsertContent', false, " <b>bolded text</b> ");
$('.tmce-active').execCommand('mceInsertContent', false, " <b>bolded text</b> ");
// TODO: run through each element
$el.each( 'input', function(el) {
console.log(el);
});
}
});
Hi Wibi,
Did you ever figure out a solution to this? Wanting to do something similar – limit what options are available on the WYSIWYG in the acf_form for user-generated content.
Thanks!
Not that this is really a solution(since it doesn’t solve 4.X), but as a final resort I upgraded to 5.6.X and I now can see the WYSIWYG editor.
Reviving this thread yet again. What demo38 suggests in the post above would be the ideal solution, ACF having a height field for WYSIWYG fields.
Thanks Elliot!
Same problem here. It doesn’t work if I try getitng the unformatted value and applying the filters as John suggested above.
The gravity forms shortcode works fine in the main editor, but not in my ACF wysiwyg editor.
guy_b solution:
//Remove WPAUTOP from ACF TinyMCE Editor
function acf_wysiwyg_remove_wpautop() {
remove_filter('acf_the_content', 'wpautop' );
}
add_action('acf/init', 'acf_wysiwyg_remove_wpautop');<code></code>
worked for me
both on field and subfield
Thanks!
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Privacy Policy. If you continue to use this site, you consent to our use of cookies.