stoutlogic / acf-builder Goto Github PK
View Code? Open in Web Editor NEWAn Advanced Custom Field Configuration Builder
License: GNU General Public License v2.0
An Advanced Custom Field Configuration Builder
License: GNU General Public License v2.0
This is because the flexible layouts inside a FlexibleContentBuilder are actually FieldsBuilders, which have the method setLocation
. But, we need setLocation
to act upon the top most level FieldsBuilder context.
It would be great to have the ability to filter the auto generated labels and titles.
Often there are just a few simple changes I need to make, but they cross a wide number of fields.
Great little bit of code you have here!
Two questions, more than issues...
ACF Pro now has the "Clone" type and it's pretty awesome. Is there some logic to use commandeering this for "object inheritance", do you think? Or is your approach enough? I just assume using the default ACF approach is typically wise??
I use ACF Pro extensions for things like choosing a GravityForm, or a registered menu for insertion on the page somehow... Would it be difficult to have a simple extension framework for acf-builder that would allow me to use these, or even better, have some convention where they're auto-discovered and usable immediately??!
Many thanks!
-Alister Cameron
Hi, i have created a cheatsheet with all default field attributes: https://gist.github.com/tdwesten/3402b2c5ef0843df6bb65afbb4835f99. It's not clear for me how to clone/fork the wiki repo and create a pull-request but maybe you can include it in the wiki.
Thanks!
Hi.
First of all, thank you very much for acf-builder. It's absolutely amazing and made my life much more sane.
I'm not sure if you've heard of the plugin WP Papi -- but I wrote a set of filters so I could use "Papi Page Types" inside of ACF.
For some reason my filters work perfectly in ACF's Field Builder but when I try to use it with acf-builder it doesn't work.
setLocation('papi_page_type', '==', 'home')
Here are my filters:
add_filter('acf/location/rule_types', function ($choices) {
$choices['Papi']['papi_page_type'] = 'Page Type';
return $choices;
});
add_filter('acf/location/rule_values/papi_page_type', function ($choices) {
$page_types = papi_get_all_page_types();
if ($page_types) {
$page_types = array_map(function($page_type) {
return [
'id' => $page_type->get_id(),
'name' => $page_type->name
];
}, $page_types);
foreach ($page_types as $page_type) {
$choices[$page_type['id']] = $page_type['name'];
}
}
return $choices;
});
add_filter('acf/location/rule_match/papi_page_type', function ($match, $rule, $options) {
if (!$options['post_id']) {
return false;
}
$page_type = papi_get_page_type_id($options['post_id']);
$selected_type = $rule['value'];
if ($rule['operator'] == '==') {
$match = ($page_type == $selected_type);
}
if ($rule['operator'] == '!=') {
$match = ($page_type != $selected_type);
}
return $match;
}, 10, 3);
Since it works when creating the fields in ACF's builder, I'm not really sure why it wouldn't be working with acf-builder.
Any help with this would be appreciated.
Hi Steve,
First of all, thanks for a cool extension for ACF.
We start using this extension a while ago and faced with a few problems.
$this->add()
just add it to internal $fields property, which then used to register fields through acf_add_local_field_group()
$this->builder()
just return an instance of Fields_Builder() class.So you can add several fields group like: $this->add( $this->builder('group1')->... , $this->builder('group2')->... )
However in this way we stuck, that when we add fields we get wrong class instance at the end (we get FieldBuilder instance, not a FieldsBuilder). We wrote small end()
method in our own child class. It looks like this:
/**
* @return Fields_Builder
*/
public function end() {
return $this->getParentContext() ? $this->getParentContext()->end() : $this;
}
So it's very similar to endFlexibleContent() method. But it's global.
setConfig('wrapper', ['some config'])
for each field, when all configs are similar. Code becomes to hard to read, because 70% of code goes to wrapper config array definitions. For each field class you have separate class and we can't overwrite FieldsBuilder to patch anything in the same way.$this->builder('some group')
->addText('my_field')
->setWrapper('30%')
->addText('another_field)
->setWrapper('70%')
...
Are you interesting in such patches? We can deliver them to you this week.
Pretty sure this is a bug..
So if I set the data like so:
$row = new StoutLogic\AcfBuilder\FieldsBuilder('page_builder', [
'title' => 'Responsive Page Builder',
'style' => 'seemless',
'hide_on_screen' => ['content_editor']
]);
$row
->setLocation('post_type', '==', 'page')
->or('post_type', '==', 'post')
->addRepeater('row', [
'title' => 'Responsive Columned Row',
'layout' => 'block'
])
->addCheckbox('style_options')
->addChoice('vert_align_center')
->endRepeater();
acf_add_local_field_group($row->build());
The data in the database is stored like so:
meta_id | post_id | meta_key | meta_value
2008 | 105 | row_0_style_options | a:1:{i:0;s:17:"vert_align_center";}
However, if I store the data like so:
$row = new StoutLogic\AcfBuilder\FieldsBuilder('page_builder', [
'title' => 'Responsive Page Builder',
'style' => 'seemless',
'hide_on_screen' => ['content_editor']
]);
$row
->setLocation('post_type', '==', 'page')
->or('post_type', '==', 'post')
->addRepeater('row', [
'title' => 'Responsive Columned Row',
'layout' => 'block'
])
->addCheckbox('style_options')
->addChoice('vert_align_center', ['title' => 'Vertical Align Center'])
->endRepeater();
acf_add_local_field_group($row->build());
The data in the database is stored like so:
meta_id | post_id | meta_key | meta_value
2008 | 105 | row_0_style_options | a:1:{i:0;s:17:"title";}
Realized this when using custom get_post_meta()
database pulls.
Hi,
I'am migrating from local acf-json fields to acf-builder and now ACF can not recognized fields as a repeater field any more. Is gives just a sting with the count of the number of repeater items, like "2".
(sorry for the unstyled/formatted code but this way is better readeble)
JSON field config
{
"key": "field_57a989b435b9a",
"label": "Componisten en Composities",
"name": "event_composers_composition",
"type": "repeater",
"value": null,
"instructions": "Selecteer hier de componisten en composities die gespeeld worden op/tijdens dit event. Wanneer een componist of compositie nog niet bestaat kan deze via het plusje toegevoegd worden.",
"required": 1,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"collapsed": "field_57a989da35b9b",
"min": 1,
"max": 0,
"layout": "table",
"button_label": "Nieuwe regel",
"sub_fields": [
{
"key": "field_57a989da35b9b",
"label": "Componist",
"name": "componist",
"type": "taxonomy",
"value": null,
"instructions": "",
"required": 1,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"taxonomy": "composer",
"field_type": "select",
"allow_null": 0,
"add_term": 1,
"save_terms": 1,
"load_terms": 0,
"return_format": "id",
"multiple": 0
},
{
"key": "field_57a98a0435b9c",
"label": "Compositie",
"name": "composition",
"type": "taxonomy",
"value": null,
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"taxonomy": "composition",
"field_type": "select",
"allow_null": 1,
"add_term": 1,
"save_terms": 1,
"load_terms": 0,
"return_format": "id",
"multiple": 0
}
]
},
ACF builder config
->addRepeater( 'event_composers_composition', [
'key' => "field_57a989b435b9a",
'label' => "Componisten en Composities",
'instructions' => "Selecteer hier de componisten en composities die gespeeld worden op/tijdens dit event. Wanneer een componist of compositie nog niet bestaat kan deze via het plusje toegevoegd worden.",
'collapsed' => "componist",
'layout' => "table",
'button_label' => "Nieuwe regel",
] )
->addField( 'componist', 'taxonomy', [
'key' => "field_57a989da35b9b",
'label' => "Componist",
'taxonomy' => "composer",
'field_type' => "select",
'add_term' => "1",
'save_terms' => "1",
'return_format' => "id",
] )
->addField( 'composition', 'taxonomy', [
'key' => "field_57a98a0435b9c",
'label' => "Compositie",
'taxonomy' => "composition",
'field_type' => "select",
'allow_null' => "1",
'add_term' => "1",
'save_terms' => "1",
'return_format' => "id",
] )
->endRepeater()
It looks like the key value is not use when registering the fields.
I'm currently using this article to know which arguments a certain field accepts.
Maybe it would be good to have it's content on the wiki
or something alike (I'm reluctant to depend on an external link that can go off anytime...).
Edit: The official ACF "guide" is missing a lot of info.
ACF 5.3.9 added new dateTimePicker and timePicker fields.
Create addDateTimePicker
and addTimePicker
methods to FieldsBuilder
Fatal error: Uncaught Error: Call to a member function setConfig() on array
This is because getFieldByName
returns a $field
which is an array.
Is it possible to modify/append/remove fields of an existing group field with the ->modifyField()
?
I'm trying to wrapping my head around it, but I just can't figure it out.
after I created Post Object field with acf-builder, post object field didn't find any results (but posts did exist, but ajax returned results as false) .. That problem is related to PHP because it didn't occur after I switched to PHP 7.1 (from 7.0)
acf-builder v1.4.0
acf-pro v5.5.14
NB: I used custom post type.
I have a few ACF front end forms that draw from multiple field groups.
I'd like to be able to do conditional logic between the different field groups. However, I get stuck with an error that ACF Builder throws when the field does not exist in the group.
It would be really awesome if there could be an additional parameter on conditional() that would ignore this check.
If I alter the array to add my conditionals they work as expected across field groups.
Thanks!
When trying to add a conditional from a field in a Flexible Layout which depends on the value of a field that is a sibling to the Flexible Content field, it fails with a FieldNotFoundException
.
A slider where normally only the background changes and the content stays fixed. But the option can be set that each slide has its own content.
$builder = new FieldsBuilder('slider');
$slider
->addTrueFalse('enable_slide_content')
->setInstructions('By default only the background will change on the slider, while the content of the first slide will remain. If you want the content to change with each slide, enable this option.')
->addWysiwyg('slider_content')
->conditional('enable_slide_content', '!=', '1')
->addFlexibleContent('slides')
->addLayout('slide')
->addImage('background')
->addWysiwyg('content')
->conditional('enable_slide_content', '==', '1');
$builder->build()
We will get a FieldNotFoundException
due to enable_slide_content
not being found in the slide layout. But this is valid ACF.
When a field isn't found, we need to traverse up the builder tree and check for the field name at each ancestor builder before throwing the exception. That is the easy part.
The hard part is doing the same in the NamespaceFieldKey transformation. Because we want the namespaced key to be that of the ancestor field, not the child field.
Potentially a hard bug to fix, might require significant rewrite. But would be a really useful feature.
Hi there,
Thanks for a nice package!
Could you please move test autoloading to "autoload-dev" section?
Cheers,
I can't find any documentation on this, how do I use the 'Hide on Screen' ACF functionality.
$banner = new StoutLogic\AcfBuilder\FieldsBuilder('banner', [
'title' => 'Banner',
'style' => 'seemless',
'hide_on_screen' => [
'content_editor',
'permalink'
]
]);
Is there a quick option similar to toggle all?
There's an error in the documentation here:
https://github.com/StoutLogic/acf-builder/wiki/conditions#complex-logic
->condition should be ->conditional
The type parameter is missing in the documentation:
https://github.com/StoutLogic/acf-builder/wiki/fields#fields
Hi we want to add conditional logic to a repeater, but how? Here the code of our try;
`
$field_group_title = โDiensten inhoudsopgaveโ;
$footer_settings = new FieldsBuilder( sanitize_title_with_dashes( $field_group_title ) );
$footer_settings
->setGroupConfig( โtitleโ, $field_group_title )
->addRadio( โtoc_typeโ, [
โlabelโ => โType inhoudsopgaveโ,
โlayoutโ => โverticalโ,
โreturn_formatโ => โarrayโ
] )
->addChoices([
โpage_scrollโ => โLinks binnen de paginaโ,
โpage_linksโ => โLinks naar andere paginaโsโ,
] )
->addRepeater(โpage_linksโ)
->addText(โtitleโ)
->addPostObject(โpage_idโ, [
โlabelโ=> โPaginaโ,
โpost_typeโ => โpageโ,
โreturn_formatโ => โidโ,
])
->endRepeater()
->addText(โtitleโ)
->conditional( โtoc_typeโ, โ==โ, โpage_linksโ)
->setLocation( โpage_templateโ, โ==โ, โtemplate-services.phpโ );
`
There's an issue with choices where the choices array gets misinterpreted and the values of the labels for the choices overwrite the values.
$finished
->addRadio('finished',[
'label' => 'Are you finished?',
'allow_null' => true,
'required' => true,
'choices' => [
'yes' => 'Yes, please send my report for review!',
'no' => 'No, save my report for later completion.',
]
])
->setLocation( 'post_type', '==', 'work_order' );
print_r($finished->build());
Results in
Array
(
[key] => group_finished
[title] => Are you finished?
[layout] => row
[fields] => Array
(
[0] => Array
(
[choices] => Array
(
[Yes, please send my report for review!] => Yes, please send my report for review!
[No, save my report for later completion.] => No, save my report for later completion.
)
[type] => radio
[name] => finished
[label] => Are you finished?
[key] => field_finished_finished
[allow_null] => 1
[required] => 1
)
)
[location] => Array
(
[0] => Array
(
[0] => Array
(
[param] => post_type
[operator] => ==
[value] => work_order
)
)
)
)
I updated from an older version to get the recursive conditional fix #26 and now I get an error where ever I used addFields with a conditional.
Uncaught exception 'Exception' with message 'No such function: conditional' in /Users/Removed/vendor/stoutlogic/acf-builder/src/ParentDelegationBuilder.php:69
Tested with a very simple setup:
$fields = new FieldsBuilder('fields');
$fields
->addText('fields_text');
$builder = new FieldsBuilder('fields_conditional');
$builder
->addSelect('select')
->addChoice('hide')
->addChoice('show')
->addText('text')
->addFields($fields)
->conditional('select', '==', 'show')
->setLocation('post_type', '==', 'page');
By the way, love the builder, quick and easy to use.
When conditionals are added using the addFields method they fail to work properly.
In the example below, the status of the 'type' field has no bearing on the conditionals. The initial settings of the conditionals are wrong based on the defaults, and changing the 'type' field value has no affect.
$linkFields = new FieldsBuilder('link_fields');
$linkFields
->addRadio('type', [
'layout' => 'horizontal'
])
->addChoices([
'none' => 'None',
'internal' => 'Internal',
'external' => 'External',
'file' => 'File'
])
->addText('label')
->conditional('type', '!=', 'none')
->addPageLink('internal')
->conditional('type', '==', 'internal')
->addUrl('external')
->conditional('type', '==', 'external')
->addFile('file')
->conditional('type', '==', 'file');
$test = new FieldsBuilder( 'test' );
$test
->addRepeater( 'links', [ 'layout' => 'block' ] )
->addFields( $linkFields )
->endRepeater()
->setLocation( 'post_type', '==', 'page' );
acf_add_local_field_group($test->build());
Generates
Array
(
[key] => group_test
[title] => Test
[fields] => Array
(
[0] => Array
(
[type] => repeater
[name] => links
[label] => Links
[key] => field_test_links
[layout] => block
[button_label] => Add Link
[sub_fields] => Array
(
[0] => Array
(
[choices] => Array
(
[None] => None
[Internal] => Internal
[External] => External
[File] => File
)
[type] => radio
[name] => type
[label] => Type
[key] => field_test_links_type
[layout] => horizontal
)
[1] => Array
(
[type] => text
[name] => label
[label] => Label
[key] => field_test_links_label
[conditional_logic] => Array
(
[0] => Array
(
[0] => Array
(
[field] => field_test_links_type
[operator] => !=
[value] => none
)
)
)
)
[2] => Array
(
[type] => page_link
[name] => internal
[label] => Internal
[key] => field_test_links_internal
[conditional_logic] => Array
(
[0] => Array
(
[0] => Array
(
[field] => field_test_links_type
[operator] => ==
[value] => internal
)
)
)
)
[3] => Array
(
[type] => url
[name] => external
[label] => External
[key] => field_test_links_external
[conditional_logic] => Array
(
[0] => Array
(
[0] => Array
(
[field] => field_test_links_type
[operator] => ==
[value] => external
)
)
)
)
[4] => Array
(
[type] => file
[name] => file
[label] => File
[key] => field_test_links_file
[conditional_logic] => Array
(
[0] => Array
(
[0] => Array
(
[field] => field_test_links_type
[operator] => ==
[value] => file
)
)
)
)
)
)
)
[location] => Array
(
[0] => Array
(
[0] => Array
(
[param] => post_type
[operator] => ==
[value] => page
)
)
)
)
ACF v5.6.2 was released today with the addition of a new Range field.
->addRange()
? ๐
Thanks a lot in advance. ACF Builder makes me very happy.
My image field variables are outputting image IDs instead of image objects now. Here is the code I am using.
$hero = new FieldsBuilder('hero');
$hero
->addImage('hero_image')
->setLocation('post_type', '==', 'page')
add_action('acf/init', function() use ($hero) {
acf_add_local_field_group($hero->build());
});
I also tried adding 'return_format' => 'array',
to the addImage
arguments but it did not affect it.
Any thoughts?
Wiki documentation shows these methods as required()
, instructions()
, and defaultValue()
, but should be setRequired()
, setInstructions()
, and setDefaultValue()
.
Otherwise they throw an exception of "No method exists."
The prefix 'set' is more inline with the setConfiguration()
method but conditional()
has no prefix and I'm all for less typing where ever possible so I vote for some wrapper methods of some kind.
Is there any way to break the chaining and pick it back up?
I'd like to dynamically set the "setLocation" and necessary "or" methods.
For example:
function createFields(){
$archiveFields = new FieldsBuilder( 'taxonomy_archive_group', [
]);
$archiveFields
->addText('taxonomy_archive_title', [
'label' => 'Title',
'instruction' => 'Replace the default archive title',
])
->addWysiwyg( "taxonomy_archive_content", [
'label' => 'Content',
'toolbar' => 'full',
'media_upload' => true,
'instruction' => 'Add optional content to the archive page.',
] )
->setLocation( 'taxonomy', '==', "all" );
$count = 0;
foreach($this->taxonomies as $taxonomy){
if($count){
$archiveFields->setLocation('taxonomy' == $taxonomy);
}
else{
$archiveFields->or('taxonomy' == $taxonomy);
}
$count++;
}
acf_add_local_field_group( $archiveFields->build() );
}
Any ideas?
If I were to do something like this:
$builder = new FieldsBuilder(
'content_areas',
array(
'button_label' => __( 'Add Content', 'my-domain' ),
)
)
->addFlexibleContent( 'flexible_content' )
->addLayout( 'hero' )
->addImage( 'hero_image' )
->addWysiwyg( 'hero_text' )
->addRepeater( 'cta', array(
'label' => __( 'Add Call to Action', YMCORE_PLUGIN_DOMAIN ),
) )
->addText( 'cta_text', array(
'label' => __( 'Text', YMCORE_PLUGIN_DOMAIN ),
) )
->addSelect( 'link_type' )
->addChoices( 'internal', 'external', 'text' )
->addPageLink( 'cta_link', array(
'post_type' => array(
'page',
'post',
'product',
),
) )
->conditional('link_type', '==', 'internal')
->addSelect( 'size' )
->addChoices( 1, 2, 3, 4 )
->addSelect( 'color' )
->addChoices( 'red', 'white', 'blue' )
->endRepeater();
The conditional outputs expects link_type
to be field of key field_cta_link_type
but in this case the field key is field_content_areas_flexible_content_hero_cta_link_type
due to proper recursion. The builder currently errors out. Would you please provide support for the conditional method within the Repeater and FlexibleContent methods?
Currently there is a workaround, but I'd like to stay consistent.
ACF 5.7 brings with it new field conditionals that only have two parameters.
Unfortunately, ACF Builder doesn't allow conditions with two parameters.
I've tried passing null but while it successfully builds, it stops the validation from working properly in certain scenarios.
Unfortunately this is causing a breaking issue for me.
The two conditionals in question are "==empty" and "!=empty".
Here's an example of how the fields output through the generate PHP option in ACF.
'conditional_logic' => array(
array(
array(
'field' => 'field_5b1305029be7d',
'operator' => '>',
'value' => '6.4999999',
),
array(
'field' => 'field_5b1305029be7d',
'operator' => '<',
'value' => '8.5000000',
),
array(
'field' => 'field_5b1305029be7d',
'operator' => '!=empty',
),
),
),
Got a php error for the $banner->build() line.
Xdebug: Fatal error: Uncaught Error: Call to a member function build() on null
Removing the function() wrapper solves the issue and the fields display properly. I used this line:
add_action('acf/init', acf_add_local_field_group($banner->build()) );
but i get 2 php notices for that new line:
Undefined offset: 0
Wonderful work btw, love the composer use, will try and get more into it in the following weeks. ๐
I'm running into an issue with this code...
$documents = new FieldsBuilder( 'documents');
$documents
->addText('documents_title')
->addRepeater( 'documents', [
'layout' => 'block',
])
ACF Builder seems to get confused when you are using the field group name as part of the field name. "documents_title" ends up getting the field name of "title".
I think the documentation should be clearer as for adding multiple choices via [key => value] arrays.
https://github.com/StoutLogic/acf-builder/wiki/choices#shorthand-for-adding-multiple-choices
It's not clear which is the "label" and which is the field "value", and as it turns out the field "value" should be the key and the field "label" should be the value which can be confusing.
I also think it would be great to support adding multiple entries in a single associative array. Currently this causes issues where the values are used as both the keys and the values in the output array.
Thanks for this awesome library!
I'm pretty sure I'll be using it on all my ACF projects moving forward.
Reading through the documentation, I wonder why you don't simply include an activate method for your FieldsBuilder that sets up the necessary hook?
When using the included autoload.php instead of composer, the repeaters and flexible fields fail when rewriting their 'Add Row' buttons.
I've tinkered with composer a little to try and properly set up the dependancies but I don't really know what I'm doing with it and don't have a lot of time to figure it out. It seems to download a lot of extra files that I don't need, particularly since this there are only two functions that rely on Doctrine.
Do you happen to have a link where I can download a compiled version that solves this problem?
Otherwise I'm just going to have to comment out those class function calls which isn't necessarily ideal for version control.
Aside from that this is a fantastic plugin, big improvement over working with the standard acf field arrays.
Before anything else, thank you very much for this awesome lib, it really prevents a lot of headaches โค๏ธ .
I was wondering about how people are using acf-builder
. Where the fields and (possibly) partial fields are located and where are they loaded?
My current folder structure is heavily inspired by Sage. I have a app/fields
directory inside my theme with each of its files returning one or more FieldBuilders
. The script in charge of loading (acf_add_local_field_group
) the fields is inside the setup.php
(part of my functions.php
)
โโโ app/ # โ Theme PHP
โ โโโ fields/ # โ ACF Fields
โ โโโ fields/partials/ # โ Partial ACF fields, for include/require
โ โโโ setup.php # โ Read and load all fields in 'app/fields'
/**
* ACF Builder initialization and fields loading
*/
define('FIELDS_DIR', dirname(__FILE__) . '/fields');
if (is_dir(FIELDS_DIR)) {
add_action('acf/init', function () {
foreach (glob(FIELDS_DIR . '/*.php') as $file_path) {
if (($fields = require_once $file_path) !== true) {
if (!is_array($fields)) {
$fields = [$fields];
}
foreach ($fields as $field) {
if ($field instanceof FieldsBuilder) {
acf_add_local_field_group($field->build());
}
}
}
}
});
}
app/fields/sample.php
$sample_field = new FieldsBuilder('sample_field');
$sample_field
->addText('title')
->addWysiwyg('content')
->setLocation('post_type', '==', 'page')
->or('post_type', '==', 'post');
return $sample_field;
Note: I haven't tested this a lot and probably the hook can be optimized (maybe switching from glob()
to scandir()
?).
Hi there,
I am having trouble updating fields when using the addFields
-functionality โ my fields disappear when editing the original FieldsBuilder.
Following the wiki entry on composing fields I assumed that I could modify the original fields but that wouldn't have any effect on the master field(s)...
When adding a FieldsBuilder to another FieldsBuilder with addFields or addLayout, that FieldsBuilder is cloned, which will lock in the fields and configs. So updating those fields at a later time on the original FieldsBuilder will not have an effect on the cloned versions. These cloned copies embedded in other FieldsBuilder can still be updated separately, so they are still mutable.
...but wouldn't destroy / hide them?
This is my setup (exemplary):
/**
* HOME -- Slider
*/
$home_slider = new FieldsBuilder('home_slider');
$home_slider
->addRepeater('slider', ['min' => 1, 'max' => 5, 'layout' => 'table'])
->addImage('image')
->addText('title', [
'wp-typography' => 'content'
])
->addWysiwyg('text', [
'wp-typography' => 'content'
])
->endRepeater()
->addText('claim');
/**
* HOME MASTER -- All home fields tabbed together
*/
$home = new FieldsBuilder('home');
$home
->addTab('Slider')
->addFields($home_slider)
->addTab('CTA Icons')
->addFields($home_cta_icons)
->setLocation('page_type', '==', 'front_page');
home
-section / -fields disappears when I modify any of included fields (f.ex. removing and/or adding a field to home_slider
after initially registering the home
-field)?acf_add_local_field_group
and re-initiating but to no avail...Sorry but either I haven't grasped the concept well enough (high probability) or this is a bug maybe?
Thanks for your insights.
Regards,
Henning
How you do register your Reuse Example?
I'm trying to:
add_action('acf/init', function() use ($section) {
acf_add_local_field_group($section->build());
});
but I'm getting a lot of warnings:
( ! ) Warning: Illegal string offset 'parent' in /srv/www/example.com/current/web/app/plugins/advanced-custom-fields-pro/pro/acf-pro.php on line 307
( ! ) Notice: Undefined index: type in /srv/www/example.com/current/web/app/plugins/advanced-custom-fields-pro/pro/acf-pro.php on line 288
Not sure if it's possible but would be great to have something like this:
Would it be possible to set a location like this?
->setLocation('page', '==', 'home')
Well, I think we could do something like this:
$page = get_page_by_path('home');
$rows = new FieldsBuilder('rows');
$rows
->addText('title')
->setLocation('page', '==', $page->ID);
But there's probably a better way. (Not sure what ACF does internally)
I'm trying to add a radio field and running into an issue with the defaultValue method.
->addRadio('project_thumbnail_extend', ['label' => 'Extend Thumbnail'])
->addChoice('none', 'None')
->addChoice('left', 'Left')
->addChoice('right', 'Right')
->defaultValue('none')
( ! ) Fatal error: Uncaught Exception: No such function: defaultValue in /Users/christianmagill/Code/Sites/influencedesign/web/app/themes/influencedesign/vendor/stoutlogic/acf-builder/src/ParentDelegationBuilder.php on line 69
No class method for google map field.
Currently if you call setLocation without calling endRepeater, the location will be set on the RepeaterBuilder, which won't actually do anything. The user really meant to add the location to the base FieldsBuilder.
I'm having some issues with a mix of flexible content fields, repeaters, and conditionals.
This code throws error
Fatal error: Uncaught StoutLogic\AcfBuilder\FieldNotFoundException: Field 'flexible_content_enabled' not found. in .../stoutlogic/acf-builder/src/FieldManager.php on line 204
$flexibleContent
->addTrueFalse( 'flexible_content_enabled', [
'label' => 'Enable Flexible Content',
'message' => 'Enable enhanced flexible content for this page.'
])
->addFlexibleContent( 'flexible_content_sections')
->addLayout('text')
->addWysiwyg('content')
->addLayout('accordion')
->addRepeater('accordion', [
'layout' => 'block',
])
->addText('accordion_title', ['label' => 'Title'])
->addWysiwyg('accordion_content', ['label' => 'Content'])
->endRepeater()
->addLayout('panel')
->addImage('panel_image')
->addWysiwyg('panel_content')
->conditional('flexible_content_enabled', '==', '1')
->setLocation( 'post_type', '==', 'page' );
However, if I move the 'panel' layout before the accordion things work as expected.
ACF now has a group field.
Would be great to see support added for it.
Since the collapsed setting for the repeater field uses the field key, which is often generated automatically, how about providing a method to set a field within a repeater as the item visible when collapsed.
$client
->addRepeater( 'contacts' )
->addText( 'first_name')
->addText( 'last_name')
->addText('nickname')
->addText('position')
->setAsCollapsedItem()
->endRepeater()
->setLocation( 'post_type', '==', 'client' );
First off, thanks for the awesome tool. This is a much less verbose way of building ACF configs.
I want to build 2 main tabs, "Cards" and "CTA".
With the build below, CTA gets added inside the repeater.
In other words I expect this:
->addTab('Cards')
->addText('cards_title')
->addRepeater('cards_list', [
'button_label' => 'Add Card',
'layout' => 'row'])
->addImage('card_icon')
->addText('card_title')
->addWysiwyg('card_content')
->addTab('CTA')
->addWysiwyg('cta_1_main_content')
->addText('cta_1_last_line')
To display like:
->addTab('Cards')
->addText('cards_title')
->addRepeater('cards_list', [
'button_label' => 'Add Card',
'layout' => 'row'])
->addImage('card_icon')
->addText('card_title')
->addWysiwyg('card_content')
->addTab('CTA')
->addWysiwyg('cta_1_main_content')
->addText('cta_1_last_line')
but it displays like:
->addTab('Cards')
->addText('cards_title')
->addRepeater('cards_list', [
'button_label' => 'Add Card',
'layout' => 'row'])
->addImage('card_icon')
->addText('card_title')
->addWysiwyg('card_content')
->addTab('CTA')
->addWysiwyg('cta_1_main_content')
->addText('cta_1_last_line')
Wondering if there is some sort of addEndOfGroup
or some such.
Hi there,
just got started using the acf-builder
and very much appreciate the library!
I ran into an issue and I suspect a bug of some sorts with acf-builder to be responsible:
I register a number of different groups / fields and they somehow overlap in the DB. Different entries are merged into one although the field names are unique and I cannot wrap my head around it. Everything seems to be set up fine...?
The value I enter in the backend for acf[field_basic_cta_title]
(save / refresh post) is being overwritten by the entry in acf[field_home_about_title]
!
Meaning I cannot set the about title at all and it just keeps ignoring what I enter into the field...
addText('about_title')
โ this is obviously not needed though since the fields are unique due to their group-labels...)acf_add_local_field_group
since that could interfere somehowNothing changes, still seeing the errors...
Field group A
/**
* BASIC -- CTA / Call to action
*/
$basic_cta = new FieldsBuilder('basic_cta');
$basic_cta
->addText('title')
->addText('subtitle')
->addText('button_label')
->addUrl('button_target')
->addRadio('style')
->addChoices('light', 'dark', 'white')
->setDefaultValue('light')
->addRadio('positon')
->addChoices(['float' => 'Nebeneinander'], ['break' => 'Untereinander'])
->setDefaultValue('float')
->setLocation('post_type', '==', 'page');
Field group B
/**
* HOME -- About-Section
*/
$home_about = new FieldsBuilder('home_about');
$home_about
->addImage('image')
->addText('title')
->addWysiwyg('text')
->setConfig('delay', 1)
->setGroupConfig('order_no', 4)
->setLocation('page_type', '==', 'front_page');
Builder
/**
* BUILD -- Now we create / register the fields
* The array should really build automatically, room for improvement here...
*/
$acf_fields = [
$basic_cta,
[...]
$home_about,
[...]
];
add_action('acf/init', function() use ($acf_fields) {
foreach ($acf_fields as $acf_field) {
if ($acf_field instanceof FieldsBuilder) {
acf_add_local_field_group($acf_field->build());
}
}
});
What I can try to further debug this? Any idea what might be causing these problems?
Any help is greatly appreciated!
Thanks & regards,
Henning
P.S.: I use ACF Fluent to retrieve / display the fields but to rule that stuff out I tested with direct calls via the_field('field_home_about_title')
but to no avail...
There is an issue, especially when composing fields, where two fields will have the same key. This causes ACF to save only one field (the one appearing second) in the admin, because ACF uses the keys as the input tag names.
ACF solves this issue when using the UI by randomly generating the keys so they are unique.
We will solve this by namespacing a field's key by its parent field groups.
For example:
$builder = new FieldsBuilder('page_content');
$builder->addFlexibleContent('sections')
->addLayout('banner')
->addText('title')
->addWysiwyg('content')
->addLayout('content_columns')
->addRepeater('columns', ['min' => 1, 'max' => 2])
->addWysiwyg('content');
The group's key will become: group_page_content
.
The flexible content areas sections
key will become: field_page_content_sections
The layout banner key will become: field_page_content_sections_banner
And the title field's key in the banner will become: field_page_content_sections_banner_title
This provides a logical semantic naming scheme for keys. They will be unique because the names of fields need to be unique. It mirrors how ACF stores fields name in the database.
The last field in the above example will have the key: field_page_content_sections_content_columns_columns_content
A user of ACF Builder shouldn't have to worry about key names, but if the user ever needs to know what the key for a particular field is, they should be able to logically deduce it.
Create an API that can be used to modify existing fields in a FieldsBuilder, including the ability to remove a field.
I'm thinking of creating the methods:
/**
* Modify an existing field
* @param $name string Field Name
* @param $modifications closure Closure that is passed a new Builder with the
* field to be modified already initialized.
* Modifications can be made and then returned. The new
* field config will replace the existing.
* @return $this FieldsBuilder
*/
function modifyField($name, $modifications);
/**
* Remove an existing field
* @param $name string Field Name
* @return $this FieldsBuilder
*/
function removeField($name);
The more interesting method is the modifyField. By passing in a function to modify the single field, we can isolate it without having to maintain an internal cursor on the FieldsBuilder. The fields config from this ModifyBuilder will replace the existing field config. This will even allow you to add new fields after a particular field.
Example:
$background = new FieldsBuilder('Background');
$background
->addImage('background_image')
->addColorPicker('background_color');
$banner = new FieldsBuilder('Banner');
$banner
->addText('title')
->addFields($background)
->modifyField('background_image', function($modifyBuilder) {
return $modifyBuilder
->instructions('Upload an image for the background of the banner')
->addTrueFalse('background_fixed')
->instructions('Check if the background should be a fixed position');
});
This would add some instructions to the background_image
field as well as insert a new background_fixed
field between the background_image
and background_color
fields.
I am building an import script where I can convert acf-json files to AcfGroups. Now I'm running into an issue with the addLayout field. In my original json file a Layout has a key
, name
, label
and display
. In the AcfGroups a layout can only have a name
. Since the label of the layout is a translated string of the name it would be great when the label can still be applied to the field.
In the original json the Layout is described this way:
"layouts": [
{
"key": "58fdc17c7498b",
"name": "page_anchor",
"label": "Verwijzing naar onderdeel",
"display": "block",
"sub_fields": [
]
}
]
My AcfGroup after converting is like this:
->addLayout( 'images_multiple', [
'key' => "58e4ad59b4665",
'label' => "Meerdere afbeeldingen",
'display' => "block",
] )
The label
doesn't show in the view anymore.
Is there a way to fix this?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.