30 May

Building a Custom Slider Block in 30 Minutes With ACF

By Elliot Condon

We recently released a new and exciting feature in ACF PRO to help PHP developers take full advantage of the new Block based editor, aka Gutenberg.

It’s called ACF Blocks and it makes light work of block type development. To demonstrate just how easy this PHP framework is to work with, I set myself a coding challenge to build a custom image slider in just 30 minutes. The recording may have gone a few minutes over, but I hope you appreciate the attention to detail and scope of information covered.

So please, poor yourself a cup of tea (or other preferred beverage) and enjoy the show ☕️.

Timeline

  • [0:52] Theme setup.
  • [2:40] Documentation.
  • [3:45] Register block type settings.
  • [6:36] Enqueue block assets.
  • [11:02] Create fields.
  • [12:20] Create block HTML.
  • [19:20] Create block JavaScript.
  • [25:30] View working block on front end.
  • [26:00] Create block styles.
  • [28:40] Fix selectable issue.
  • [33:50] Set default alignment setting.
  • [35:00] Wrapping up.

Complete code

For those looking to create the same block, or just wanting to peruse the complete code, here are the 4 files created in this demonstration.

functions.php

// Register a slider block.
add_action('acf/init', 'my_register_blocks');
function my_register_blocks() {

    // check function exists.
    if( function_exists('acf_register_block_type') ) {

        // register a testimonial block.
        acf_register_block_type(array(
            'name'              => 'slider',
            'title'             => __('Slider'),
            'description'       => __('A custom slider block.'),
            'render_template'   => 'template-parts/blocks/slider/slider.php',
            'category'          => 'formatting',
            'icon'              => 'images-alt2',
            'align'             => 'full',
            'enqueue_assets'    => function(){
                wp_enqueue_style( 'slick', 'http://cdn.jsdelivr.net/npm/[email protected]/slick/slick.css', array(), '1.8.1' );
                wp_enqueue_style( 'slick-theme', 'http://cdn.jsdelivr.net/npm/[email protected]/slick/slick-theme.css', array(), '1.8.1' );
                wp_enqueue_script( 'slick', 'http://cdn.jsdelivr.net/npm/[email protected]/slick/slick.min.js', array('jquery'), '1.8.1', true );

                wp_enqueue_style( 'block-slider', get_template_directory_uri() . '/template-parts/blocks/slider/slider.min.css', array(), '1.0.0' );
                wp_enqueue_script( 'block-slider', get_template_directory_uri() . '/template-parts/blocks/slider/slider.min.js', array(), '1.0.0', true );
              },
        ));
    }
}

template-parts/blocks/slider/slider.php

<?php

/**
 * Slider Block Template.
 *
 * @param   array $block The block settings and attributes.
 * @param   string $content The block inner HTML (empty).
 * @param   bool $is_preview True during AJAX preview.
 * @param   (int|string) $post_id The post ID this block is saved to.
 */

// Create id attribute allowing for custom "anchor" value.
$id = 'slider-' . $block['id'];
if( !empty($block['anchor']) ) {
    $id = $block['anchor'];
}

// Create class attribute allowing for custom "className" and "align" values.
$className = 'slider';
if( !empty($block['className']) ) {
    $className .= ' ' . $block['className'];
}
if( !empty($block['align']) ) {
    $className .= ' align' . $block['align'];
}
if( $is_preview ) {
    $className .= ' is-admin';
}

?>
<div id="<?php echo esc_attr($id); ?>" class="<?php echo esc_attr($className); ?>">
    <?php if( have_rows('slides') ): ?>
        <div class="slides">
            <?php while( have_rows('slides') ): the_row(); 
                $image = get_sub_field('image');
                ?>
                <div>
                    <?php echo wp_get_attachment_image( $image['id'], 'full' ); ?>
                </div>
            <?php endwhile; ?>
        </div>
    <?php else: ?>
        <p>Please add some slides.</p>
    <?php endif; ?>
</div>

template-parts/blocks/slider/slider.scss

.slider {
    padding: 0 0 5px;

    .slides {

        img {
            height: 80vh;
            width: auto;
            padding: 2vh;
        }
    }

    // Fix selectable bug.
    &.is-admin {
        &:before {
            display: block;
            content: "";
            top: 0;
            left: 0;
            right: 0;
            bottom: 40px;
            position: absolute;
            z-index: 1;
        }
    }
}

template-parts/blocks/slider/slider.js

(function($){

    /**
     * initializeBlock
     *
     * Adds custom JavaScript to the block HTML.
     *
     * @date    15/4/19
     * @since   1.0.0
     *
     * @param   object $block The block jQuery element.
     * @param   object attributes The block attributes (only available when editing).
     * @return  void
     */
    var initializeBlock = function( $block ) {
        $block.find('.slides').slick({
            dots: true,
            infinite: true,
            speed: 300,
            slidesToShow: 1,
            centerMode: true,
            variableWidth: true,
            adaptiveHeight: true,
            focusOnSelect: true
        });     
    }

    // Initialize each block on page load (front end).
    $(document).ready(function(){
        $('.slider').each(function(){
            initializeBlock( $(this) );
        });
    });

    // Initialize dynamic block preview (editor).
    if( window.acf ) {
        window.acf.addAction( 'render_block_preview/type=slider', initializeBlock );
    }

})(jQuery);

About the Author