Blog posts under the ACF tag https://webdevstudios.com/tags/acf/ WordPress Design and Development Agency Mon, 15 Apr 2024 16:00:17 +0000 en-US hourly 1 https://wordpress.org/?v=6.6.2 https://webdevstudios.com/wp-content/uploads/2022/07/cropped-wds-icon.white-on-dark-60x60.png Blog posts under the ACF tag https://webdevstudios.com/tags/acf/ 32 32 58379230 Integrating Advanced Custom Fields + Gutenberg Into wd_s https://webdevstudios.com/2019/10/24/advanced-custom-fields-gutenberg-wd_s/ https://webdevstudios.com/2019/10/24/advanced-custom-fields-gutenberg-wd_s/#respond Thu, 24 Oct 2019 16:00:16 +0000 https://webdevstudios.com/?p=21285 With version 5.8 of Advanced Custom Fields (ACF), a new way to build Gutenberg blocks was introduced. The mission statement of ACF with this pivotal update was to: …radically change the perception of block development in Gutenberg by reducing learning time, hurdles, environment setup and JavaScript knowledge to an absolute minimum. They have done exactly Read More Integrating Advanced Custom Fields + Gutenberg Into wd_s

The post Integrating Advanced Custom Fields + Gutenberg Into wd_s appeared first on WebDevStudios.

]]>
With version 5.8 of Advanced Custom Fields (ACF), a new way to build Gutenberg blocks was introduced. The mission statement of ACF with this pivotal update was to:

…radically change the perception of block development in Gutenberg by reducing learning time, hurdles, environment setup and JavaScript knowledge to an absolute minimum.

They have done exactly that.

For quite some time now, our wd_s starter theme has been powered in part by Advanced Custom Fields. Using the Flexible Content Field, we were able to create a page builder-esque experience for users. This experience lived on the backend when editing posts and pages. We didn’t set out to create a full-on page builder or content builder like the ones we’ve used in the past. We simply understood the need for users to have full control over their content, the placement of that content, and the overall structure of their posts and pages.

And it worked! It worked for a long time. In fact, it still works beautifully.

With the advent of WordPress 5.0, Gutenberg became the hot topic when discussing the CMS. Some absolutely loved the new experience while others reviled it for myriad reasons, such as it felt rushed, it wasn’t fully accessible, and that it was an oftentimes confusing experience.

For us, the issues we experienced working with and building alongside Gutenberg in its development was enough to raise a few red flags. Despite Gutenberg going live in 5.0, we stood back for a moment to evaluate everything before diving head-first into action with the new system. After all, what we had already established wasn’t broken. So, there was no need to “fix” it.

In order to keep our existing workflow in place, we enabled the Classic Editor plugin on new projects to disable Gutenberg and continue working with our tried and true ACF Flexible Content Block system. Once the ACF 5.8 betas and release candidates began rolling out with Gutenberg block support, we began testing the new features with our existing system.

What did we find? Well, to no surprise to anyone on the team, we found that it did exactly what it promised. We were able to spin up new Gutenberg blocks and begin planning a move away from Flexible Content and into a full-on Gutenberg experience.

First Steps

The first thing we needed to figure out when making the transition to ACF-powered Gutenberg Blocks was what we actually needed to include from our existing Flexible Content Blocks. Starting with a blank slate, our content blocks included things like a Call To Action, Hero, and Generic Content block which was a simple WYSIWYG field.

With the robust suite of blocks already available with Gutenberg, we knew we could trim down what we needed to bring over. So, we began to trim the excess and examine if the other blocks we needed served a larger purpose as custom blocks than by “replacing” them with core blocks. We were able to rip the Generic Content block out pretty easily as a standard content block can be added anywhere with Gutenberg.

For our other blocks, though, we found that there were enough little bits and bobbles attached to them that we didn’t want to give up. For instance, our blocks all include the same set of global options including the ability to set a background image, background video, or background color. With the video and image background options, we also include the ability to apply an overlay to make text easier to read when overlaid on the background.

We also have some bonus functionality like Start Date and End Date for those blocks you wish to only display for a specific period of time. Our Hero was also just a bit more fleshed out than what we felt we could accomplish with the core Gutenberg blocks, like setting the aforementioned background options, title, text, and optional link stylized as a button.

Our existing blocks also included Recent and Related Posts. While Gutenberg does offer a Latest Posts widget out of the box, there was just a bit more we were doing with ours that we didn’t want to give up. For instance, the core Latest Posts widget allows for you to specify a post category from which to draw posts but not post tags. You are also limited to selecting a single category or tag, while our block allows for selecting multiple terms in each taxonomy. Along with the previous global block options mentioned and some visual differences, we felt it important to include our own custom block.

Once we got through with our internal review process to determine which blocks we would port over, we were left with:

  • Accordion
  • Carousel
  • Call To Action
  • Fifty-Fifty
  • Hero
  • Recent Posts
  • Related Posts

Creating Your First Block

The first step in creating your Advanced Custom Fields + Gutenberg block is to hook into acf/init and register your block. To ensure that your blocks all have the same global options, though, you’ll first want to establish your baseline supports features for the block:

View the code on Gist.

With this, you’re saying two things: that you only want two layout options for your blocks and that you want to allow for your blocks to have an anchor, or ID, set. In general, the wd_s Flexible Content Blocks had conformed to the width of the content container with the option to go full-width, meaning they will span 100% of the browser width. This is common with blocks with backgrounds, especially heroes. Allowing for an anchor, or ID, was essential as this allows for users to link to other blocks either from the same page or externally.

Next, you’ll need to actually register your block:

View the code on Gist.

This is the important stuff. You’re giving your block a name, description, some keywords, and enqueuing your scripts amongst setting some other baseline ACF settings. Once you have this in place, you simply need to hook in your function like so: add_action( 'acf/init', '_s_acf_init' )

Since you’re calling some other functions and functionality in your block registration, though, you also need to ensure you’re properly tapping into the groundwork Advanced Custom Fields has laid for you.

Adding a Category

In your block registration above, you’ve set your category as wds-blocks. However, that’s a custom category and doesn’t exist by default, which means Gutenberg won’t know how to find these new, fabulous blocks you’re building. Because of that, you need to register your category in a separate function:

View the code on Gist.

Be sure your category slug matches the category name you’re prescribing exactly!

Registering Scripts and Styles

For the Accordion block, you’re calling the _s_acf_enqueue_accordion_scripts callback function to register the scripts necessary to power your block. In general, you may not need to register any scripts—just styles. For the Accordion and Carousel blocks coming form wd_s, though, there is some additional JavaScript needed to make sure the blocks work on the backend.

After all, if you’re looking to deliver a similar experience on the backend as you’re providing on the frontend, you want your JavaScript to work so users can see just how the Accordion collapses and expands before publishing their content. With that in mind, you have to enqueue your scripts:

View the code on Gist.

Within this function, you’re also calling a function to enqueue styles, which looks like this:

View the code on Gist.

You’ll notice the very first thing in both functions is the check for is_admin(). You don’t need to enqueue your scripts anywhere else than on the backend through these methods. The wd_s theme already compiles and enqueues all of the necessary JavaScript and CSS files for the frontend, and here you’re simply concerned with making sure those styles are reflected when adding a block in the editor.

Adding a Field Group

Once your code is in place, the next step is to create the fields for the block. After all, what you’ve done so far is just tell Advanced Custom Fields to create something called “Accordion,” but you’ve yet to actually put something in that block.

Just like with any other Field Group you’d want to create, you’ll navigate to the Custom Fields menu in the Dashboard and click “Add New.” Next, create the fields you need for your block:

ACF Field Group settings page

These will, of course, differ from block to block and for your own personal use cases. All in all, though, this should be familiar to anyone who has worked with ACF in the past. The next step is where things get changed up a bit.

With the previous Flexible Content Block system in wd_s, the “Active” option would be toggled to “Off” for all of the block Field Groups. Then, each block would be cloned in the actual Flexible Content Block Field Group. This helped keep things a bit more sane in the backend. Each block existed as a standalone Field Group, and other reusable Field Groups could be created and cloned into each block like the Background Options and Display Options.

Now, however, you simply need to set your Location rules based on the block you’re creating. Since this is the Accordion block, you want to tell ACF to display these fields when the Block is equal to Accordion. Plus, you now need to ensure you set the Active option to “On” otherwise your block won’t display in the Gutenberg block selector:

ACF Field Group Location settings

And that’s how easy it is to create and register a block in ACF! You can now select your block from the block selector when editing your post… but nothing will happen.

Creating Block Templates

Before anything can actually display, you’ll need to create a template. Ain’t that just the way life works sometimes?

In the block registration way up above in this post, you may have noticed that we’ve set render_callback to _s_acf_block_registration_callback. This is where you’ll let Advanced Custom Fields know exactly where to find the template to display your block.

Keeping with the DRY mentality and not wanting to overload the theme with callbacks for every single block, wd_s includes a handy dandy function which will convert the block name to a slug and inject it into a core WordPress function to grab a template file. This function also checks to make sure the block isn’t expired, which is important because if your block is expired, you don’t want to display it on the frontend at all!

The end result is this tidy little 22-line chunk:

View the code on Gist.

What lives in your actual template file is up to you and will change based on your block, but the important bits to mention are:

  1. Make sure you specify the correct template path
  2. Make sure you name your blocks and template files consistently
  3. In the case of wd_s, add an extra bonus for the Expired Block functionality

Since you have the ability to hide blocks after a specific date, you need a way to communicate this to users on both the frontend and backend. This is easy on the frontend. You simply don’t display the block at all. On the backend, though, you don’t want to hide the block completely because then a user can never edit it or even remove it. That block lives there now forever. It’s comfortable and can’t be evicted. It has attained squatter’s rights.

With a couple of little functions, and some CSS, you’re able to show editors that a block is expired while still allowing them to edit the block in the backend. This is super useful if a user has a block that runs once a week every month and you need to edit the content each month. Now, your users can place your block and let it sit quietly expired with your newest content updates until the new Start Date rolls around.

You’ll begin with this:

View the code on Gist.

And build on that with the following pair of helper functions which check for a block’s expiration and add a class to the block if the block is no longer active:

View the code on Gist.

Now when a block expires, your users will see a helpful notice in the backend:

wd_s Gutenberg expired block message that says, "Your block has expired. Please change or remove the Start and End dates under Other Options to display your block on the frontend.

Our Full Setup

After much back and forth in building, testing, building, testing, and reviewing we are super excited to announce that wd_s is now a Gutenberg-first theme! We merged in our pull request to convert all of our Flexible Content Blocks over to native Gutenberg blocks via ACF about a month ago and are looking forward to seeing how we can grow and expand the awesome functionality ACF provides.

There’s a lot going on here, so feel free to take a peek at our acf-gutenberg.php file to see how everything works together in the wd_s Github repo.

There, you can follow the breadcrumb trail to see some other magic we’re doing with our template files, template tags, and global block options like background elements. While there will always be improvements to be made, those will come in time as we use this new system more and more in real-world situations.

What have you built with the Advanced Custom Fields + Gutenberg integration and where can you see it going from here? Let us know in the comments below!

The post Integrating Advanced Custom Fields + Gutenberg Into wd_s appeared first on WebDevStudios.

]]>
https://webdevstudios.com/2019/10/24/advanced-custom-fields-gutenberg-wd_s/feed/ 0 21285
Creating, Extending, and Upgrading Custom ACF Fields That Use Select2 https://webdevstudios.com/2019/09/17/acf-fields-that-use-select2/ https://webdevstudios.com/2019/09/17/acf-fields-that-use-select2/#comments Tue, 17 Sep 2019 16:00:27 +0000 https://webdevstudios.com/?p=20970 Advanced Custom Fields (ACF) has been around for quite a while now, and it’s super popular. We’re on version 5.x now, and the earliest dated reference documentation I could find was for ACF 2.0 in 2011. There have been some bumps along the way. One of the more recent issues was compatibility of the Select2 Read More Creating, Extending, and Upgrading Custom ACF Fields That Use Select2

The post Creating, Extending, and Upgrading Custom ACF Fields That Use Select2 appeared first on WebDevStudios.

]]>
Advanced Custom Fields (ACF) has been around for quite a while now, and it’s super popular. We’re on version 5.x now, and the earliest dated reference documentation I could find was for ACF 2.0 in 2011. There have been some bumps along the way.

One of the more recent issues was compatibility of the Select2 JavaScript library versions. It was mostly because two other popular plugins, Yoast’s WordPress SEO and WooCommerce, also use Select2. What is Select2? It’s the kick-ass library that lets you transform boring dropdowns to amazing searchable and formattable ones:

A screen grab image of a searchable time zone dropdown menu.

So what’s the big deal with ACF? Well, Select2 has gone through some major revisions as well, most notably the latest Select2 Version 4, which is not backwards compatible with Select2 version 3.x. So, if ACF brings in Version 4 and WooCommerce brings in Version 3, we’ve got problems.

Thankfully, ACF came up with an elegant way to deal with these incompatibilities by checking to see if another plugin had enqueued Version 3 and falling back to using a Select2 Version 3 adapter.

View the code on Gist.

Future-proof it or just fix it?

So, what does this have to do with custom ACF fields? Well, in my case there was an old custom-built ACF field that used Select2. To add the Select2 library to the dropdown, it used a JavaScript call to acf.add_select2() to add it. If you notice in the gist above, acf.newSelect2() was added in ACF 5.6.5, and it replaces acf.add_select2(). In the future, how can we avoid running into this problem? In practice, there are two options:

  1. Extend an existing ACF field that is close to what you want to do.
  2. Create a new (or updating an existing) custom field and use ACF to add Select2.

Your first option is the best one. Here’s why: it simplifies your code investment by leveraging as much as possible from ACF. But, I’m also including the quick-fix instructions specific to the Select2. That way, if you have an existing field that you just need to get working for the time being, you can do that as well.

Option 1: Simplify by extension

One of the fields I needed to fix that used acf.add_select2() was strikingly similar to an existing ACF field—the relational field called Taxonomy. The built-in ACF Taxonomy field also uses Select2. The only difference between the custom field that needed repair and the built-in one is that the custom field would display terms from multiple categories, instead of just one. I had an a-ha moment on a call with Corey Collins when he suggested aloud to let ACF handle the hard work and to just tweak what I needed. Brilliant idea, Corey!

The custom field used to look like this:

View the code on Gist.

Because the AcfFieldMultipleCategories class was essentially a copy of class-acf-field-taxonomy.php, it was almost 600 lines of code.

Instead of extending acf_field, I was able to instead extend acf_field_taxonomy and reduce the PHP code by half and get rid of the custom JavaScript entirely.

View the code on Gist.

What’s different?

Here’s a brief breakdown of the things that are different in the AcfFieldMultipleCategories class and why. You can compare much of the code above to what’s in class-acf-field-taxonomy.php for reference.

  1. The class doesn’t get defined until init. This is because ACF doesn’t load the parent acf_field_taxonomy class right away.
  2. Using initialize instead of __construct: ACF 5.6.0 switched to using initialize instead of __construct so I wanted to follow suit. Our class calls parent::initialize() to get all of the defaults from the taxonomy field, then sets only the fields we want to override.
  3. AJAX actions for wp_acf: These actions are present on the parent, but when they’re registered, they reference a specific instance of an object—the parent acf_field_taxonomy class. We redefine them here to get called on our AcfFieldMultipleCategories instance.
  4. Extra CSS classes in wrapper_attributes: We need our custom field to be rendered with a CSS class of acf-field-taxonomy. This is what the ACF Select2 library is looking for to attach to fields. Select2 will behave exactly how it would on a taxonomy field; we’re just changing the query that happens on the back end.
  5. get_ajax_query has been overridden: It gets called from the parent ajax_query method. We override this to get a result set of terms from multiple taxonomies.
  6. load_value has been overridden and simplified to remove filtering.
  7. render_field has been overridden and simplified to only render a select field because that’s the only option we’re allowing.
  8. render_field_select has been overridden to call a custom get_term_by_id function.
  9. render_field_settings has been overridden to remove the Appearance setting (remember we only want it to display a dropdown). We also removed the Create Terms option, as we won’t be saving any new terms because they’re coming from multiple taxonomies.

Is it a lot? Sure, but it’s far less duplication than before and through simplification, making it less prone to bugs and errors. But if that’s still too much, can you take the easy way out…

Option 2: Just update Select2 calls

This option is an easier short-term solution but may postpone further compatibility issues. Just switch any calls from add_select2 to newSelect2. Any parameters to that function that were previously in snake_case need to be changed to camelCase. Here’s a diff of one that I updated:

-		acf.add_select2( $select, {
+		acf.newSelect2( $select, {
 			ajax: 1,
- 			ajax_action: "acf/fields/post_object/query",
- 			allow_null: 0,
+			ajaxAction: "acf/fields/post_object/query",
+			allowNull: 0,

That’s it. I chose this option for a different and far more complex custom ACF field. It had four inputs in one field, which is nothing like any built-in fields. This one is just going to stay as-is and will try to follow the ACF JavaScript conventions.

Getting Permission

When possible, I prefer the first method of doing things because it’s a better long term solution. You can do Option 2 in less than an hour and then still have time left over to convince your manager that Option 1 is better for the long term. Get some time scheduled to fix it the right way, and it’s a win-win for you and your project.

The post Creating, Extending, and Upgrading Custom ACF Fields That Use Select2 appeared first on WebDevStudios.

]]>
https://webdevstudios.com/2019/09/17/acf-fields-that-use-select2/feed/ 1 20970
Advanced Custom Fields and Gutenberg https://webdevstudios.com/2018/12/11/advanced-custom-fields-and-gutenberg/ https://webdevstudios.com/2018/12/11/advanced-custom-fields-and-gutenberg/#comments Tue, 11 Dec 2018 17:00:36 +0000 https://webdevstudios.com/?p=19363 WordPress 5.0 ships with a new editor called Gutenberg. Here at WebDevStudios, we’re excited to build custom editorial solutions using Gutenberg and to see how the experience evolves from the classic editor. With that said, we’re huge fans of Advanced Custom Fields (ACF). It provides a robust set of field types that enables us to create Read More Advanced Custom Fields and Gutenberg

The post Advanced Custom Fields and Gutenberg appeared first on WebDevStudios.

]]>
WordPress 5.0 ships with a new editor called Gutenberg. Here at WebDevStudios, we’re excited to build custom editorial solutions using Gutenberg and to see how the experience evolves from the classic editor.

With that said, we’re huge fans of Advanced Custom Fields (ACF). It provides a robust set of field types that enables us to create flexible and friendly content management solutions for our clients. The time we save from writing, testing, and maintaining code with ACF makes it worth paying for an ACF PRO license. Our wd_s  starter theme includes commonly-used content blocks built on ACF.

ACF 5.8 has added support for Gutenberg. You can add ACF fields to a Gutenberg block without any JavaScript code. In this article, you will learn how to build a custom Gutenberg block for hero area using ACF without writing a single line of JavaScript code.

Adventurous, right?

ACF and Gutenberg

To build custom blocks using Gutenberg, you must be familiar with writing Modern JavaScript using the latest syntax (ES6, ES7, ES8, JSX), as well as creating components using React. To see this in action, here are some code examples to demonstrate a classic “Hello World” example for Gutenberg.

Custom Gutenberg Block with Vanilla JavaScript:

View the code on Gist.

Custom Gutenberg block with Modern JavaScript:

View the code on Gist.

The second example is smaller and cleaner but requires a build tool setup to compile Modern JavaScript syntax and JSX into browser supported code. You can get a head start by using create-gutenberg-block created by Ahmad Awais to scaffold a Gutenberg block without learning how to set up build tools.

Side Note: Learn JavaScript Deeply

Matt Mullenweg recommended that the WordPress community Learn JavaScript deeply in 2015. If you’re a frontend developer, this still applies—not only for Gutenberg but JavaScript frameworks like React, Angular, and Vue are now widely-adopted and in-demand. Here are some resources to level up your JavaScript skills:

Hero Block

You will be recreating a simpler version of the hero area that is included with wd_s. This is the end result of the custom Gutenberg block that you will create:

Requirements:

  1. Gutenberg (WordPress 5.0)
  2. Advanced Custom Fields PRO 5.8.0

Step 1: Register the Hero Block

ACF introduced acf_register_block function with 5.8, which you will be using to register a custom Gutenberg Hero Block.

The example below shows how to register the hero block. You can drop this function in the functions.php file of your theme.

View the code on Gist.

To learn more details about each parameter of the acf_register_block  function, visit the official documentation.

Step 2: ACF field group for Hero Block

A field group is a set of fields that can be assigned to a WordPress post, page, widget, etc., and now a custom Gutenberg blocks registered with acf_register_block.

Next, you’ll add a new field group for the Hero Block from the Custom Fields page.

The basic field requirements for this block are:

  • Tab field: Block Content
  • Title field
  • Text field
  • Button text field
  • Button URL field
  • Tab field: Background Options
  • Background image field

 

 

Next, assign the field group to the Hero Gutenberg Block.

To reiterate, Block is a new rule type in ACF which refers to all Gutenberg blocks registered with acf_register_block.

Save your changes!

This is how these fields will display in Gutenberg:

Step 3: Set up the Hero Block template

Custom Gutenberg Block created with ACF will use a template file to display it within the Gutenberg editor and on the frontend.

Create a template file template-parts/gutenberg/hero.php within your theme’s folder to match with render_template parameter of acf_register_block defined in Step 1.

The template file will contain HTML markup to add layout and return data from the fields.

View the code on Gist.

The get_field function from ACF is used to get data from the ACF fields.

The rest of the markup is basic HTML for setting up the Hero block’s layout. Just to appreciate the power of this feature by ACF, I want to point out that you didn’t have to write a single line of JavaScript. That’s amazing!

This is how the block looks within the Gutenberg editor:

Step 4: Styling the Hero Block template.

The final step is to style your Gutenberg Block.

To do this, you will be using the enqueue_block_assets action. This hook is used to enqueue assets for Gutenberg’s editor and frontend. If you want to have a separation between frontend and backend styling, you can use enqueue_block_editor_assets to enqueue assets only within the Gutenberg editor.

Drop the following code in your functions.php file to enqueue the stylesheet for your custom Gutenberg Hero Block:

View the code on Gist.

Create gutenberg.css in the root of your theme’s folder and drop the following code for styling the block:

View the code on Gist.

CSS is compiled from Sass.

This finishes your block setup with zero JavaScript code. Congratulations! This is how your Hero Block will look in the Gutenberg editor:

And this is how it will look on the frontend:

 

In my opinion, ACF provides a solid platform that fills the gap between PHP and JavaScript developers. ACF makes the whole Gutenberg Block creation process easier, faster and reliable. Even though I can foresee the limitation of ACF when a complex Gutenberg Block will come in action, I still appreciate and applaud ACF’s approach on making the whole process super simple for all level of developers.

Technically, acf_register_block is extremely powerful considering that a filter can be added to settings array to be used by other themes and plugins to make it even better (or worse).

The post Advanced Custom Fields and Gutenberg appeared first on WebDevStudios.

]]>
https://webdevstudios.com/2018/12/11/advanced-custom-fields-and-gutenberg/feed/ 10 19363
Filtering ACF Content Blocks with WordPress Hooks & Filters https://webdevstudios.com/2018/11/29/filtering-acf-content-blocks-with-wordpress-hooks-filters/ https://webdevstudios.com/2018/11/29/filtering-acf-content-blocks-with-wordpress-hooks-filters/#respond Thu, 29 Nov 2018 17:00:22 +0000 https://webdevstudios.com/?p=19433 Here at WebDevStudios, we do quite a bit with Flexible Content Blocks in Advanced Custom Fields (ACF). If you aren’t familiar with the plugin, ACF allows for the creation of a multitude of custom meta field types using a graphical user interface (GUI) in the WordPress Dashboard. You can do almost anything with these fields—from simple Read More Filtering ACF Content Blocks with WordPress Hooks & Filters

The post Filtering ACF Content Blocks with WordPress Hooks & Filters appeared first on WebDevStudios.

]]>
Here at WebDevStudios, we do quite a bit with Flexible Content Blocks in Advanced Custom Fields (ACF). If you aren’t familiar with the plugin, ACF allows for the creation of a multitude of custom meta field types using a graphical user interface (GUI) in the WordPress Dashboard. You can do almost anything with these fields—from simple text and URL inputs to searching for posts and pages and building image galleries.

ACF allows you to power your site with robust customization options, which you can use to create and manage dynamic pages. Instead of being locked into a set of page templates where the functionality and layout are tied directly to the theme’s files, building pages with ACF Flexible Content Blocks puts the power of customization into your hands as a site manager and editor. You can add, remove, and rearrange blocks as needed and have full control over the content within each of those blocks.

Sometimes, though, simply customizing the content within those blocks isn’t enough. Sure, it’s nice enough to be able to edit the title of a block or select a different set of Featured Posts to display. But, what if you don’t want to have to get that far into the weeds with customizing your pages and posts? What if you would rather set a category on a page or post and rely on the content blocks to figure out in which category your page resides and update the block content dynamically?

We recently discovered a use-case for such a situation and were able to find some fun and interesting ways to extend our standard ACF Flexible Content Blocks. Instead of requiring anybody to manually edit a set of content blocks already added to a page, we were able to add functionality into our blocks that look for the page’s category. Then, by the magic of wizards (or WordPress, I guess), we can filter the output of the block drastically cutting the time it takes to update an entire page of content.

So, what did we do and how can you use it, too? Let’s dig in and find out!

Our Block Code

Let’s start with a common case and a block which would be super handy to filter by a post’s category: Call To Action. This block ships with wd_s out of the box, so we’ll start first by looking at the markup driving it:

View the code on Gist.

You may be asking yourself (or me, though I promise I can’t hear you), “Why would I need to dynamically filter that? Can’t I just edit the block’s contents?” Well, yes, you could just edit the block’s contents and be on your way. But, what if you use that same Call To Action on, say, a dozen pages which all share the same category? Suddenly, you realize you want to change the title of the Call To Action if that one specific category is set. Rather than having to edit a dozen individual posts, you could utilize a filter in your theme’s code to handle that work. That means less time editing posts and more time sitting back, sipping coffee and admiring a job well done.

How do you get there, though? First, let’s modify the block to be able to accept filters:

View the code on Gist.

This starts off similarly to the initial block but there are some crucial changes in place. First, you’re creating a $default_args array immediately after you grab the block’s values. This stores the values you are saving to the block, like the title or button URL when you edit the page.

Directly after you set those items in the new $default_args array, you’re creating a second array called $block_args which merges the $default_args array with any potential array passed in via a WordPress filter. This means that if you never use the filter, nothing will ever change with regard to how this block works on the frontend. You’ll still edit the block as you normally would and see the expected updates when you save the page.

However, if you hook into _s_cta_block_args (as you’ll see later on), you can pass in your own custom values for all of the information you set in our $default_args array earlier in the snippet.

The final set of changes comes in how you output your data. Instead of simply calling the individual variables, like $title, you need to look inside of your $block_args array. Remember, even if you’re not passing in any filters for the current condition, you’re still creating a brand new array called $block_args which holds all of your data. So, instead of outputting $title you now need to output $block_args['title']. This is a small and subtle but pivotal change, otherwise the filtering won’t work once you get to that point.

Applying Our Filters

Now for the real magic. It’s all well and good to have the ability to filter the content, but how do you actually go about hooking in and filtering anything? With the magic of a WordPress filter, you can hook into the aforementioned _s_cta_block_args filter and run wild. You will need to be sure to test the conditions for these filters in various scenarios. If you simply hook into this filter without any conditional statement within it, the contents of the block will be altered everywhere it is used throughout the site.

View the code on Gist.

So, it’s important to know when and why you need to filter your content. In this case, you’re going to check to see if the block is being used on a page or post which is set in a specific category. If it is not, you simply return your $block_args array. This means that you don’t alter anything and the block functions as it normally would. If you do find yourself on a page with that category set, though, the fun and excitement can begin.

You’ll need to pay attention to the array keys and be sure that they match what was set in your block’s template file, otherwise, you won’t see your filtered changes reflected on the frontend. In the example above, you’re filtering almost everything–the block’s title, the button URL and text, and you’re adding a CSS class so you can target this block with special styles sometime down the road.

Wrapping Up

And that’s it! You now have the ability to filter the content in a block without having to actually edit a page. This could be a massive time-saver if you realize that you need to change the URL of a button or link in a block that you’ve added to dozens of pages all which exist within the same category. Plus, once you’ve done it once it becomes second-nature to be able to add this same ability to your other existing blocks.

What other uses do you think you could come up with for filtering blocks this way?

The post Filtering ACF Content Blocks with WordPress Hooks & Filters appeared first on WebDevStudios.

]]>
https://webdevstudios.com/2018/11/29/filtering-acf-content-blocks-with-wordpress-hooks-filters/feed/ 0 19433
Creating a Global Options Component in Gutenberg https://webdevstudios.com/2018/04/12/creating-a-global-options-component-in-gutenberg/ https://webdevstudios.com/2018/04/12/creating-a-global-options-component-in-gutenberg/#respond Thu, 12 Apr 2018 16:00:40 +0000 https://webdevstudios.com/?p=18285 At WebDevStudios (WDS), we’ve seen many iterations of page builders and page builder-esque tools over the years. I think it’s safe to say that the experimentation began with CMB2 and led us down an exciting path that included a handful of full-fledged page builders and our own custom-built page builder before we finally came to rely Read More Creating a Global Options Component in Gutenberg

The post Creating a Global Options Component in Gutenberg appeared first on WebDevStudios.

]]>
At WebDevStudios (WDS), we’ve seen many iterations of page builders and page builder-esque tools over the years. I think it’s safe to say that the experimentation began with CMB2 and led us down an exciting path that included a handful of full-fledged page builders and our own custom-built page builder before we finally came to rely on Advanced Custom Fields (ACF) as a way to allow clients the freedom to edit, arrange, and customize their pages and posts. While ACF isn’t a page builder per se, its robust customization has given us the ability to present our clients with a similar level of customization found in strict page builders. Now… enter Gutenberg.

Here’s what the CEO of our company, Brad Williams, recently tweeted about it, “WordPress Gutenberg is not a page builder.”

While not a full-fledged page builder, Gutenberg does allow for the type of customization we have been building via ACF for several years. It certainly changes how that customization occurs, and part of our directive here at WDS has been to take what we have built in ACF and transfer it to Gutenberg. So, what is the first stop on the ACF-to-Gutenberg brain train? It’s converting our set of globally-used block options.

Part of what we include with all of our default ACF blocks is a panel of options to allow for some major visual customizations. These options include the usage of a background image, video, or color, customizing the font color, adding animation options and any custom CSS classes that a user may need to further tweak their block once it hits the frontend. As important as it was for us to make sure these options are available to use on all of our Gutenberg blocks, it was also important for us to ensure:

  • The options are easy to include for developers
  • The options exist in one central location to keep our code DRY
  • The options work visually in a Gutenberg block the same way they work currently in an ACF block

Getting Started

My first step was to get completely overwhelmed. Digging into reusable Gutenberg components is no small task. After running through Zac Gordon’s Gutenberg Development course, I was comfortable building blocks and even components in the Inspector Controls panel, but this took on a whole new level. We needed conditional fields and, as stated earlier, a way to keep this code as DRY as possible to avoid simple mistakes from being made when attempting to include the Background Options on a new block.

Our options panel is broken down into separate parts, so it made sense to tackle these one at a time rather than trying to do all of the things in one sitting. We’ve broken down the various options into:

  • Background Options
  • Text Options
  • Other Options

For the sake of this post, we’ll be focusing on Background Options. Before we get into the code, take a look at the file structure for our component.
View the code on Gist.

Let’s start by looking at what lives in our outlier JavaScript files, because their contents will be what makes the rest of our component work.

First, we have attributes.js. Like any regular Gutenberg block, our component needs attributes to save when its values are edited. We broke this out into an individual file because it would help keep our index.js file clean, and it makes it easier to import our attributes into our blocks later on. Inside of our attributes.js file we have:
View the code on Gist.

What we’re doing here is setting our default attribute types and then exporting the entire set of attributes for use later on. Now if we ever need to update our Background Options attributes, we won’t have to edit them across all of our various blocks. We’ll just edit them once here and let them trickle down into our blocks wherever they are being used.

Next up is our classes.js file. Neither classes.js, inline-styles.js, or video.js are required by Gutenberg; these are files that will drive markup for functionality for us later on when we begin building our blocks. In classes.js, we’re checking to see which Background Type is selected (image, video, color, or none) and adding a matching class to our block:
View the code on Gist.

In inline-styles.js, we’re doing a similar thing as in classes.js . We’re checking to see which Background Type has been selected and then pulling in its value as an inline style. Specifically, this checks to see if we are using a background color or a background image and sets that value as an inline style on our parent container if either is found:
View the code on Gist.

Finally, our video.js file outputs the video selected when using the “video” Background Type. Since we can’t set a video to be a background element of a container the same way we can with a color or image, we have to output the video markup in the container and then position everything via CSS. Inside of our video.js file is where we’ll keep the markup for our video output:
View the code on Gist.

With that out of the way, it’s time to start building the functionality of our component. The first thing we need to do in our index.js file is import any core WordPress and Gutenberg dependencies we’ll be using. These will vary slightly from component to component depending on what types of fields you’ll be using, but for us, we wound up with:
View the code on Gist.

In order to keep our main file clean, as noted above, we broke out as many things as possible into individual files. Next, we have to import them into the index.js file and export them so we can use them later on in our individual blocks. That last part will make sense once we get into creating a block. For now, let’s just assume you trust me, we import and export our internal dependencies like so:
View the code on Gist.

Now, we can actually get into the nitty-gritty of building out the functionality for our Background Options component. First, we need to create a new function and export it so we can use it in our blocks:
View the code on Gist.

Note that we’re passing in props —this is important because we’re going to be using these to check, get, and set attributes throughout this function. Before we get into any of that, though, let’s set some variables for our various event listeners so we have something to hook into when we want to change the background color, background image, or anything else we’ll be customizing in this function:
View the code on Gist.

Now, it’s time for the fun stuff! The first piece of the puzzle we’ll be building out is our Background Image Selector. Let’s kick this off:
View the code on Gist.

Before we do anything, let’s check to see which Background Type has been selected. If the user has selected the “video” Background Type, then there’s no point in displaying the Background Image Selector.
View the code on Gist.

Now that we know for sure whether or not we’re actually selecting an image, we can build out some further functionality. With this next bit of code, we want to check to see if we have a background image already set. If we do, then we don’t need to display the MediaUpload component. But, if we’re starting fresh and want to select an image, then we definitely need that component handy. This utilizes the core Gutenberg MediaUpload component that we imported way at the top of this file:
View the code on Gist.

But, what if we already have an image? In that case, we want to display the image we’ve already uploaded as well as a way to remove it and replace it with a new image:
View the code on Gist.

Since this comes after our first conditional check, we don’t need to check whether or not an image is already set. If we’ve made it this far in our function, then we know we already have an image saved and are safe to try and output the saved image.

Next, let’s prepare our Video Background Selector. The code here is going to look somewhat similar to the Image Selector we just built, but of course, there are little touches here and there that make it its own special thing. It begins just the same way by setting a const:
View the code on Gist.

Just as we did with the image, let’s check which Background Type has been selected before proceeding:
View the code on Gist.

Now, we need to see if we have a video saved already. This is pretty darn identical to our Image Selector above, except it’s specifying “video” as the value for “type” in the MediaUpload component:
View the code on Gist.

We want our users to know which video they’ve uploaded to a particular block. So if a video is already set, we’re going to display a non-playing version of it in our component:
View the code on Gist.

Finally, we want to be able to select a background color if the “color” Background Type is selected. Just like with the two previous examples, let’s start things by setting a const for our Color Selector:
View the code on Gist.

This particular selector is going to be a lot more streamlined, as we don’t have to worry about including an uploader or outputting anything visually in our component that doesn’t already come from core Gutenberg. First things first, let’s check our background type:
View the code on Gist.

And if we know that we’re looking to set a background color, then we know that we need to display Gutenberg’s PanelColor and ColorPalette components:
View the code on Gist.

We’re almost there! At this point, we’ve created the core functionality of all three of our Background Types: image, video, and color. But, how do we actually tell our component which one of these options we want to use? And how do we actually get any of this stuff to show up in our Inspector Controls panel?

To start, we’re going to veer from what we’ve been doing so far and simply return rather than setting a const. At this point, we’re actually beginning to output the contents of our component rather than building its individual parts. First, we need to start a PanelBody container:
View the code on Gist.

Inside of PanelBody , we want to have unique rows. One will house the Background Type select while the other will house the output for whichever value we have selected. Each of these will live inside of a core Gutenberg PanelRow component. For our Background Type selector, we’ll need to build a selector dropdown and, lucky for us, we can use another core Gutenberg component! We also want this particular option to be visible regardless of the selected Background Type because we want to give our users the ability to change Background Type at any time.
View the code on Gist.

Gutenberg really comes through and makes this easy for us. We’re simply creating a select dropdown and specifying the labels and values for each of our options. Remember all of the conditionals we set earlier in our function where we checked for backgroundType? This SelectControl is what sets the backgroundType value and allows those conditionals to work. Make sure your value for each of these match up to what you’re going to be checking for elsewhere in your functions.

Lastly, we need a way to set our background image, video, or color. Remember when we created our const variables above and did all of the work of setting our image, video, and color values? The reason we set those as const variables the way we did is so we could create a cleaner output in this return. Just below the PanelRow we created for the Background Type selector, create another PanelRow to output our settings:
View the code on Gist.

You might be yelling at me right now that this won’t work—that we’re simply outputting all three of these individual Selectors with no rhyme or reason. Untrue! If you recall, when we set our const variables above, we also checked to see if the selected Background Type matched the type of Selector we were about to display. Inside of all of those const variables, we’re already checking to see which Background Type is set and either bailing if we don’t have a match or displaying the settings if we do. Checking inside of the const lets us keep a very clean and streamlined render at the end of our function.

To see the full version of this file, check out the Gist here!

If you’re still with me… good! We just have a few more things to do before we can see this sucker when editing a block. So far, we’ve built the functionality out but have yet to add it to a block. We’ll do that next. I won’t go over how to build the entire block, because that’s a blog post for another day. If you want to see the end product of what we have in our Default Block as it stands now, you can view that here.

For our purposes, we’ll assume you have the block built already and are looking to add a Background Options panel to your block.

First, we need to make sure you’re importing InspectorControls from Gutenberg core in addition to whatever other blocks you’re importing:
View the code on Gist.

Remember back in our Background Options index.js file when we imported our attributes.js, classes.js, inline-styles.js, and video.js files then immediately exported them? We did that so we could easily and cleanly import all of our necessary Background Options pieces in one line:
View the code on Gist.

With that one line, we’re gaining access to the entire BackgroundOptions function we built as well as all of the goodies that we’re using to make our magic happen. Now, we need to actually begin including those things in our blocks. The first step is to include our attributes. Like I’ve said before, we strive to keep our code as DRY as possible and this was no exception. We didn’t want our developers to have to copy and paste a complete set of attributes every single time they created a new block, and we especially didn’t want to have to update a bunch of different files if our attributes changed at any point in the future.

The beautiful thing here is that with another sweet, single line we can import all of our attributes:
View the code on Gist.

Next, we need to actually output our options panel. This happens inside of the edit function of our Gutenberg block and, again, by utilizing exports and imports we’ve made the process super easy. First, we check to see if our block is in focus and, if it is, we add our InspectorControls panels:
View the code on Gist.

Again, with that single line, we’re pulling in all of our BackgroundOptions functionality and passing in our props so we’ll have access to them in our component. This is really what makes the whole thing work. Without those few lines, we won’t have anything displayed in our InspectorControls panel.

Finally, we need to output some markup so our block will listen for our Background Options and behave accordingly. For the next section, just know that you will have to output the same markup in both your edit and save functions to ensure your block functions properly and displays your options on both the frontend and backend.

We’re using a section tag to wrap our block, and because we want to add a class and potentially inline styles based on our Background Options choices, we’ll need to tell our markup to do just that:
View the code on Gist.

With those in place, we’ll now be able to see the background image or background color set for our block when using the “image” or “color” Background Type. But, what if we’ve selected “video” and have uploaded a beautiful MP4 to display in the background? Easy! We just need to display our video output using the import from the top of our block.
View the code on Gist.

To see the full version of this file, check out the Gist here.

And that’s it!

I know, I know… “that’s it.” There’s a lot to digest here. A lot of this may have been overwhelming to read (it was overwhelming to write, too!), but I would encourage you to do exactly what I did when I started building this component. Do it wrong, get confused, and then start over. When I first started trying to build the Background Options component, I did it by starting with some code Jeffrey de Wit wrote. I had a hard time understanding what he was doing or why it was working. So, I broke everything down to its simplest form. Instead of going all out and building the entire Background Options panel, I started with just the Background Type select dropdown so that I could understand how values were passed between files and functions and just how everything worked at its core.

Once I had an understanding of that one component, I was able to piece everything else together in my brain to make it work. Along the way, I had some help from Eric Fuller, a noted JavaScript guru around these parts, who helped me break everything out into individual files and keep things as smartly-written as possible.

After the Background Options were taken care of, building the Text Options and Other Options panels were a bit of a breeze. They are far less complex than dealing all that came with building the Background Options panel, so they came together much more easily. As always, you can follow along with the progress of our WDS Blocks plugin and check out how we’re handling our other global components in our Github repo.

What brave, new worlds have you come across when getting to know Gutenberg? What have you built that seemed crazy at first, but wound up being completely worth the confusion and frustration that comes with trying to do something outside of your comfort zone? And, what are you looking forward to in Gutenberg as its inclusion in WordPress core gets closer and closer? Let us know in the comments below.

The post Creating a Global Options Component in Gutenberg appeared first on WebDevStudios.

]]>
https://webdevstudios.com/2018/04/12/creating-a-global-options-component-in-gutenberg/feed/ 0 18285