Roots Discourse

Using ACF Builder with Sage

TL;DR: Looking for a way to reference fields defined in my builder in my views.

Sorry in advance if this is obvious :grimacing: ! I’ve been searching the documentation but haven’t found a way to display the values of fields created with the page builder / flexible content in my templates. For example, I’m pulling a logo into header.blade using the following in my App.php controller:

  public function headerLogo()
  {
    return get_field('header_logo', 'option');
  }

and the following in header.blade.php:

  @if ($header_logo)
    <img src="{{ $header_logo['url'] }}" class="logo" alt="{{ $header_logo['alt'] }}"/>
  @endif

This is working great! What I’m now looking for is a sane way to return all the values attached to fields/page.php. For example, here’s a field group I’ve defined in fields/components/call-to-action.php (which has been included in my builder):

<?php

namespace App;

use StoutLogic\AcfBuilder\FieldsBuilder;

$config = (object) [
    'ui' => 1,
    'wrapper' => ['width' => 50],
];

$callToAction = new FieldsBuilder('Call to Action');

$callToAction
    ->addGroup('Call to Action')
        ->addText('heading', ['wrapper' => $config->wrapper])
          ->setInstructions('Heading for your CTA.')

        ...

    ->endGroup();

return $callToAction;

Thanks for looking!

Hey @zack - take a look at the Controller docs section on ACF here and let us know if that helps get you pointed in the right direction! https://github.com/soberwp/controller/#advanced-custom-fields-module

1 Like

PS - also check out the Blade Debugger and Blade Coder sections of that doc and give them a test. They can be very helpful.

1 Like

My directives package may also be of use for displaying values in your views that do not contain heavy logic.

It has no docs yet (I’ve been swamped)– but have a look at ACF.php.

2 Likes

Definitely a great place to start. Looks like all of my flexible content is stored within an array called “components”. Should probably be fine once I figure out the best way to iterate over it!

Thanks for passing this along. My php wasn’t strong enough to figure out what was happening by reviewing ACF.php alone, but I’ll definitely hang onto this for future reference.

More or less it’s just basic blade directives for ACF.

An example for your Call to Action group being:

@group('call_to_action')
   <h2>@sub('heading')</h2>
   <p>[...]</p>
@endgroup

Same goes for using normal fields, @field('example'), @sub('example'), etc. There are also helpers for handling conditionals like:

@hasfield('example')
   <h2>@field('example')</h2>
@endfield

@field can accept multiple parameters to help with fields that return an array, such as image:

<img src="@field('my_image', 'url')" class="image" alt="@field('my_image', 'alt')" />

That being said, I just realized I forgot to add the above @field functionality (accepting arguments like you need for your header_logo) to @option– I’ll add it shortly followed by actual documentation for each field so people can start making use of these. :slight_smile:

3 Likes

@Log1x this looks awesome! I installed and I’m trying it out, but I can’t seem to get any output. I created a foreach loop that is pulling in partials based on acf_fc_layout (based on the recommendations of nathobson and jasonbaciulis):

@foreach ($components as $component)
  @include('partials/builder/'.$component->acf_fc_layout)
@endforeach

Here are the contents of the partial, which is successfully loading, but not printing any of the field values:

<div class="image-text-overlay">
  @group('image-text-overlay')
    <div>
      <h2>@sub('heading')</h2>
    </div>
    <div><img src="@sub('image', 'url')" alt="@sub('image','alt')"></div>
  @endgroup
  @debug
</div>

Here’s what’s in debug:

Anything I might be missing?

Did you figure this out? Is the group key supposed to be image_text_overlay?

Does {!! var_dump(have_rows('image-text-overlay')) !!} return true?

For what it’s worth, https://github.com/Log1x/sage-directives now has docs & has been updated. :slight_smile:

1 Like

Hey Brandom, I really appreciate your effort to help us write such cleaner and more maintainable code. Although there’s one big gotcha that took me hours to debug that I think you should warn people when using this technique. It took me a long time to figure out why the custom fields were not working in a production server but were working in my local mac environment, it turned out to be all about the letter case in the file and folder names.

As a quick example, if you create a file named Button.php and try to call get_field_partial('components.button') , it won’t work because it will look for a button.php (lower cased). Same thing for folder names such as Fields and fields .

I think that because all other files and folders around the app folder are all capitalized (since they are classes), I also happened to capitalized the custom fields. Big problem is that it didn’t care at all in my mac environment, but the moment I’ve uploaded it to the linux production server nothing worked hehe, taking some good hours to find out why and update everything.

Thanks again for the awesome article!

I want to reuse fields on multiple options pages.
The catch is that options are basically all one page as far as ACF is concerned, so they need unique keys per options page.

I’m adding normal fields, not flexible content fields.

I tried both the ->addFields($header) method and the ->addFields(get_field_partial('partials.header')) method, and tried setting the ‘key’ on the FieldsBuilder and addFields.

With the above attempts, the same keys get used (can tell this quickly because the fields on new options pages are filled out already with text i entered through wp-admin on old options pages)

Is there a way to add a prefix to the key or change the key after doing addFields? I don’t see any mention in the ACFBuilder docs about prefixing a key. Or am I going about this the wrong way?

Thanks

Edit: This seems more of an ACFBuilder question so I submitted it on their repo. I’ll update here if a solution is found.

With the current implementation of ->addFields, I don’t see a sane way in ACF Builder’s source to pull this off for the entire field group; especially with the FieldsBuilder instance protecting $config and $fieldManager.

I can see this being useful if implemented though as shown in the issue you opened.

1 Like

5.7.10 release right now! It solves several Gutenberg issues:

  • Fix - Fixed bug preventing metaboxes from saving if validation fails within Gutenberg.
  • Fix - Fixed bug causing unload prompt to show incorrectly within Gutenberg.
  • Fix - Fixed JS error when selecting taxonomy terms within Gutenberg.
  • Fix - Fixed bug causing jQuery sortable issues within other plugins.
  • Tweak - Improved loading translations by adding fallback from region to country when .mo file does not exit.
  • Tweak - Improved punctuation throughout admin notices.
  • Tweak - Improved performance and accuracy when loading a user field value.
  • Dev - Added filter ‘acf/get_locale’ to customize the locale used to load translations.
  • Dev - Added filter ‘acf/allow_unfiltered_html’ to customize if current user can save unfiltered HTML.
  • Dev - Added new data storage functions acf_register_store() and acf_get_store().
  • Dev - Moved from .less to .scss and minified all css.
  • i18n - Updated French translation thanks to Maxime Bernard-Jacquet.
  • i18n - Updated Czech translation thanks to David Rychly.

@zack

1 Like

Hey, After following Brandon’s guide I am having an issue. I can create fields and they display in WordPress backend, however, the problem is with Media. No image is showing and the loading circle is swirling all the time.
I also notice that removing the code from the bottom of setup.php file helps (code below), but of course, it is necessary to use the builder.
Any ideas how to resolve this problem guys? Is any of you had this problem.

PS. I am using WP 5.0.3

/**
* Initialize ACF Builder
*/
add_action('init', function () {
    collect(glob(config('theme.dir').'/app/fields/*.php'))->map(function ($field) {
        return require_once($field);
    })->map(function ($field) {
        if ($field instanceof FieldsBuilder) {
            acf_add_local_field_group($field->build());
        }
    });
});

Not really sure why that is happening, but there’s either a PHP error which should be in your error log or a JS error which would be in devtools console. If so, can you share them?

First time using ACF Builder and it’s so great.

I did however have an issue with the field layouts not working if I use an integer for layout width.

Example:
'wrapper' => ['width' => '30'], renders fine
'wrapper' => ['width' => 30], like from the guide, resulted in a broken layout in the dashboard

Hey,

@Log1x I have to say that your guide is very helpful and as well as all your public projects on Github.

I need to create something like a “list generator” in a ‘FlexibleContent’.
I have a variety of icon lists, some of them contain icon title and text, some of them wrapped by link, and some not for both, etc…
but if I create my true_false field for conditional above and outside of the repeater field and the conditional passed inside the repeater, the FieldManager.php class throw FieldNotFoundException("Field 'ahs_title' not found.") because it is not the same parentContext.

Someone has ever dealt with it in some way?

I’d be happy to get help

Thanks

fields/page.php

$flex_content = new FieldsBuilder( 'flex_content' );

$flex_content
->setLocation('post_type', '==', 'page');

$flex_content
->addFlexibleContent('flex_content', ['label' => '', 'button_label' => 'Add Content to Page'])
->addLayout(get_field_partial('components.list-generator'))
->endFlexibleContent();


return $flex_content;

fields/components/list-generoter.php

$list_generator = new FieldsBuilder('list_generator');

$list_generator
    ->addTrueFalse('has_title')
    ->addRepeater('list_generator')
    ->addText('title')->setWidth(20)->conditional('has_title','==',1)
    ->endRepeater();

return $list_generator;

Hi everyone,

Has anyone managed to create a dynamic Select using user created values in a previous ACF?

Exemple:
1st ACF (The user is creating categories)

->addRepeater('categories', [
        'label' => 'Categories',
        'min' => 1,
        'button_label' => 'Add Category',
        'layout' => 'block',
        ])
       ->addText('category');

2nd ACF (in another tab)

->addRepeater('forms', [
        'label' => 'Forms',
        'min' => 1,
        'button_label' => 'Add Form',
        'layout' => 'block',
        ])
       ->addText('name')
       ->addSelect('select_category', [
        'choices' => [FIELDS FROM category REPEATER]);

Thanks a lot :slight_smile:

I’d stick to a filter:

add_filter('acf/load_field/name=cart_item', function ($field) {
    $field['choices'] = collect(
        get_field('grocery_store', 'option')
    )->map(function ($item) {
        return $item['food'];
    })->all();

    return $field;
});
$options
    ->addRepeater('grocery_store', ['button_label' => 'Add Food'])
        ->addText('food');

$options
    ->addRepeater('shopping_cart', ['button_label' => 'Add Grocery'])
        ->addSelect('cart_item');

Mind you, it won’t take effect til save without Javascript.

Works like a charm ! Thanks man!