Help with Dynamic Data for Image Carousel in Bricks Builder

Hi everyone,

I’m trying to display a dynamic image gallery in a Bricks Builder carousel using a custom field gallery_images that stores image IDs separated by commas. However, the carousel only shows the first image repeatedly instead of displaying each ID as individual slides.

The website: Quarto MC – Sala 106 ®

My goal is for Bricks to use the gallery_images field to show each image as a separate slide without needing ACF or shortcodes. Does anyone know how to set up Bricks Builder to accomplish this? Any tips would be appreciated!

Here the code that I’m using:

function add_custom_metabox() {
    add_meta_box(
        'custom_metabox',
        'Image Gallery',
        'custom_metabox_callback',
        'post',
        'normal',
        'high'
    );
}
add_action('add_meta_boxes', 'add_custom_metabox');

function custom_metabox_callback($post) {
    wp_nonce_field(basename(__FILE__), 'custom_metabox_nonce');
    $stored_meta = get_post_meta($post->ID);
?>
    <div>
        <input type="hidden" id="gallery_image" name="gallery_images" value="<?php echo esc_attr(get_post_meta($post->ID, 'gallery_images', true)); ?>" />
        <button type="button" id="upload_gallery_button" class="button"><span class="dashicons dashicons-format-gallery" style="font: normal 18px / 1 dashicons; line-height: 28px;"></span> Add Imagens</button>
        <div id="gallery_images_container" class="sortable">
            <?php
            $image_ids = get_post_meta($post->ID, 'gallery_images', true);
            if (!empty($image_ids)) {
                $image_ids = explode(',', $image_ids);
                foreach ($image_ids as $image_id) {
                    $image_url = wp_get_attachment_image_src($image_id, 'thumbnail');
                    echo '<div class="gallery-image" data-image-id="' . esc_attr($image_id) . '"><img src="' . esc_url($image_url[0]) . '" /><a href="#" class="remove-image">Remove</a></div>';
                }
            }
            ?>
        </div>
    </div>

    <script>
        jQuery(document).ready(function($) {
            var frame;
            $('#upload_gallery_button').on('click', function(e) {
                e.preventDefault();
                if (frame) {
                    frame.open();
                    return;
                }
                frame = wp.media({
                    title: 'Selecione ou envie suas imagens',
                    button: { text: 'Usar estas imagens' },
                    multiple: true
                });
                frame.on('select', function() {
                    var attachments = frame.state().get('selection').toJSON();
                    var image_ids = [];
                    attachments.forEach(function(attachment) {
                        image_ids.push(attachment.id);
                        $('#gallery_images_container').append('<div class="gallery-image" data-image-id="' + attachment.id + '"><img src="' + attachment.sizes.thumbnail.url + '" /><a href="#" class="remove-image">Remove</a></div>');
                    });
                    $('#gallery_images').val(image_ids.join(','));
                });
                frame.open();
            });

            $('#gallery_images_container').sortable({
                update: function(event, ui) {
                    var image_ids = [];
                    $(this).children('.gallery-image').each(function() {
                        image_ids.push($(this).data('image-id'));
                    });
                    $('#gallery_images').val(image_ids.join(','));
                }
            });

            $(document).on('click', '.remove-image', function(e) {
                e.preventDefault();
                $(this).parent().remove();
                var image_ids = [];
                $('#gallery_images_container').children('.gallery-image').each(function() {
                    image_ids.push($(this).data('image-id'));
                });
                $('#gallery_images').val(image_ids.join(','));
            });
        });
    </script>
    <style>
		#poststuff .inside {
			margin: 10px 0 0;
		}
        .gallery-image {
            display: inline-block;
            margin-right: 10px;
            cursor: move;
        }
        .gallery-image img {
            display: block;
			margin-top: 10px;
            max-width: 100px;
            height: auto;
        }
        .gallery-image a {
            display: block;
            text-align: center;
            margin-top: 5px;
            color: #b32d2e;
        }
    </style>
<?php
}

function save_custom_metabox($post_id) {
    if (!isset($_POST['custom_metabox_nonce']) || !wp_verify_nonce($_POST['custom_metabox_nonce'], basename(__FILE__))) {
        return $post_id;
    }
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return $post_id;
    }
    if (!current_user_can('edit_post', $post_id)) {
        return $post_id;
    }
    if (isset($_POST['gallery_images'])) {
        update_post_meta($post_id, 'gallery_images', sanitize_text_field($_POST['gallery_images']));
    } else {
        delete_post_meta($post_id, 'gallery_images');
    }
}
add_action('save_post', 'save_custom_metabox');

Honestly it is not very easy to understand your code, if you don’t wrap it in a pre-textblock. :wink:

That being said, your custom field gallery_images needs to return an array like the one below for it to work with the bricks carousel:

$image_gallery = [1047,1045,1043];

// if you var_dump it:
array(3) {
  [0]=>
  int(1047)
  [1]=>
  int(1045)
  [2]=>
  int(1043)
}

Cheers Suat

@SuatB is not working.

Here the code organized:

function add_custom_metabox() {
    add_meta_box(
        'custom_metabox',
        'Image Gallery',
        'custom_metabox_callback',
        'post',
        'normal',
        'high'
    );
}
add_action('add_meta_boxes', 'add_custom_metabox');

function custom_metabox_callback($post) {
    wp_nonce_field(basename(__FILE__), 'custom_metabox_nonce');
    $stored_meta = get_post_meta($post->ID);
?>
    <div>
        <input type="hidden" id="gallery_image" name="gallery_images" value="<?php echo esc_attr(get_post_meta($post->ID, 'gallery_images', true)); ?>" />
        <button type="button" id="upload_gallery_button" class="button"><span class="dashicons dashicons-format-gallery" style="font: normal 18px / 1 dashicons; line-height: 28px;"></span> Add Imagens</button>
        <div id="gallery_images_container" class="sortable">
            <?php
            $image_ids = get_post_meta($post->ID, 'gallery_images', true);
            if (!empty($image_ids)) {
                $image_ids = explode(',', $image_ids);
                foreach ($image_ids as $image_id) {
                    $image_url = wp_get_attachment_image_src($image_id, 'thumbnail');
                    echo '<div class="gallery-image" data-image-id="' . esc_attr($image_id) . '"><img src="' . esc_url($image_url[0]) . '" /><a href="#" class="remove-image">Remove</a></div>';
                }
            }
            ?>
        </div>
    </div>

    <script>
        jQuery(document).ready(function($) {
            var frame;
            $('#upload_gallery_button').on('click', function(e) {
                e.preventDefault();
                if (frame) {
                    frame.open();
                    return;
                }
                frame = wp.media({
                    title: 'Selecione ou envie suas imagens',
                    button: { text: 'Usar estas imagens' },
                    multiple: true
                });
                frame.on('select', function() {
                    var attachments = frame.state().get('selection').toJSON();
                    var image_ids = [];
                    attachments.forEach(function(attachment) {
                        image_ids.push(attachment.id);
                        $('#gallery_images_container').append('<div class="gallery-image" data-image-id="' + attachment.id + '"><img src="' + attachment.sizes.thumbnail.url + '" /><a href="#" class="remove-image">Remove</a></div>');
                    });
                    $('#gallery_images').val(image_ids.join(','));
                });
                frame.open();
            });

            $('#gallery_images_container').sortable({
                update: function(event, ui) {
                    var image_ids = [];
                    $(this).children('.gallery-image').each(function() {
                        image_ids.push($(this).data('image-id'));
                    });
                    $('#gallery_images').val(image_ids.join(','));
                }
            });

            $(document).on('click', '.remove-image', function(e) {
                e.preventDefault();
                $(this).parent().remove();
                var image_ids = [];
                $('#gallery_images_container').children('.gallery-image').each(function() {
                    image_ids.push($(this).data('image-id'));
                });
                $('#gallery_images').val(image_ids.join(','));
            });
        });
    </script>
    <style>
		#poststuff .inside {
			margin: 10px 0 0;
		}
        .gallery-image {
            display: inline-block;
            margin-right: 10px;
            cursor: move;
        }
        .gallery-image img {
            display: block;
			margin-top: 10px;
            max-width: 100px;
            height: auto;
        }
        .gallery-image a {
            display: block;
            text-align: center;
            margin-top: 5px;
            color: #b32d2e;
        }
    </style>
<?php
}

function save_custom_metabox($post_id) {
    if (!isset($_POST['custom_metabox_nonce']) || !wp_verify_nonce($_POST['custom_metabox_nonce'], basename(__FILE__))) {
        return $post_id;
    }
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return $post_id;
    }
    if (!current_user_can('edit_post', $post_id)) {
        return $post_id;
    }
    if (isset($_POST['gallery_images'])) {
        update_post_meta($post_id, 'gallery_images', sanitize_text_field($_POST['gallery_images']));
    } else {
        delete_post_meta($post_id, 'gallery_images');
    }
}
add_action('save_post', 'save_custom_metabox');

So i guess the problem with your code is not bricks related. I copied your code, and i have your custom meta-box, but when i add images, save and reload the page, i can see that they are not stored.

I used the bricks code-element to var_dump, the post meta-data like this:

<pre>
<?php
  global $post;
  var_dump(get_post_meta($post->ID));  
?>
</pre>

and this is my result (after trying to add images to your custom meta-box)

array(7) {
  ["_edit_lock"]=>
  array(1) {
    [0]=>
    string(12) "1732288101:1"
  }
  ["_cmplz_scanned_post"]=>
  array(1) {
    [0]=>
    string(1) "1"
  }
  ["_edit_last"]=>
  array(1) {
    [0]=>
    string(1) "1"
  }
  ["_pingme"]=>
  array(1) {
    [0]=>
    string(1) "1"
  }
  ["_encloseme"]=>
  array(1) {
    [0]=>
    string(1) "1"
  }
  ["cmplz_hide_cookiebanner"]=>
  array(1) {
    [0]=>
    string(0) ""
  }
  ["gallery_images"]=>
  array(1) {
    [0]=>
    string(0) ""
  }
}

Maybe you need to check first, if your meta-box correctly stores it’s input.
Cheers Suat

Thanks, @SuatB! It’s working now. Here’s the correct code:

Gallery Metabox:

// Função para registrar a metabox
function register_custom_metabox() {
    add_meta_box(
        'custom_gallery_metabox', // ID da metabox
        'Image Gallery', // Título da metabox
        'render_custom_metabox', // Função que renderiza a metabox
        'post', // Tipo de post onde a metabox será exibida
        'normal', // Contexto (onde a metabox será exibida)
        'high' // Prioridade
    );
}
add_action('add_meta_boxes', 'register_custom_metabox');

// Função para renderizar o conteúdo da metabox
function render_custom_metabox($post) {
    // Adiciona o nonce para validação do formulário
    wp_nonce_field(basename(__FILE__), 'custom_metabox_nonce');
    
    // Recupera as imagens salvas (IDs)
    $gallery_images = get_post_meta($post->ID, 'gallery_images', true);
    $gallery_images = is_array($gallery_images) ? $gallery_images : [];  // Garantir que seja um array

    // Exibe o campo para adicionar imagens
    echo '<input type="hidden" id="gallery_images" name="gallery_images" value="' . esc_attr(implode(',', (array) $gallery_images)) . '" />';
    echo '<button class="button" id="upload_image_button" style="padding-left: 7px; padding-right: 7px; margin-top: 5px;"><span class="dashicons dashicons-format-gallery" style="display: inline-block; width: 20px; height: 20px; line-height: 1; vertical-align: middle; margin: 0 2px;"></span> Upload Images</button>';
    
    // Exibe as miniaturas das imagens selecionadas
    if (!empty($gallery_images)) {
        echo '<ul id="gallery_images_list" style="display: flex; flex-wrap: wrap; padding: 0; list-style-type: none; cursor: move;">';
        foreach ($gallery_images as $image_id) {
            // Obtém a URL da miniatura da imagem
            $image_url = wp_get_attachment_image_url($image_id, 'thumbnail');
            if ($image_url) {
                echo '<li class="gallery-image-item" data-id="' . esc_attr($image_id) . '" style="margin-right: 10px; display: inline-block; cursor: move; text-align: center; width: 150px;">';
                echo '<img src="' . esc_url($image_url) . '" style="width: 150px; height: 150px; object-fit: cover;"/>';
                echo '<a class="remove-gallery-image" style="cursor: pointer; color: #b32d2e; font-size: 13px; text-decoration: underline; display: block; margin-left: auto; margin-right: auto;">Remove</a>';
                echo '</li>';
            }
        }
        echo '</ul>';
    }

    // Script para o Media Uploader e reordenação com jQuery UI
    echo '<script type="text/javascript">
        jQuery(document).ready(function($) {
            var mediaUploader;

            // Função de upload de imagens
            $("#upload_image_button").click(function(e) {
                e.preventDefault();
                if (mediaUploader) {
                    mediaUploader.open();
                    return;
                }
                mediaUploader = wp.media.frames.file_frame = wp.media({
                    title: "Select Images",
                    button: { text: "Select Images" },
                    multiple: true
                });

                mediaUploader.on("select", function() {
                    var selection = mediaUploader.state().get("selection");
                    selection.each(function(attachment) {
                        var image_ids = $("#gallery_images").val().split(",");
                        if (image_ids.indexOf(attachment.id.toString()) === -1) {
                            image_ids.push(attachment.id);
                        }
                        $("#gallery_images").val(image_ids.join(","));
                    });

                    // Atualiza a lista de imagens no front-end
                    updateGalleryImages();
                });

                mediaUploader.open();
            });

            // Função para atualizar as imagens na galeria
            function updateGalleryImages() {
                var image_ids = $("#gallery_images").val().split(",");
                var gallery_list = $("#gallery_images_list");
                gallery_list.empty();
                image_ids.forEach(function(image_id) {
                    var image_url = wp.media.attachment(image_id).get("url");
                    var html = \'<li class="gallery-image-item" data-id="\' + image_id + \'" style="margin-right: 10px; display: inline-block; cursor: move; text-align: center; width: 150px;">\';
                    html += \'<img src="\' + image_url + \'" style="width: 150px; height: 150px; object-fit: cover;"/>\';
                    html += \'<a class="remove-gallery-image" style="cursor: pointer; color: #b32d2e; font-size: 13px; text-decoration: underline; display: block; margin-left: auto; margin-right: auto;">Remove</a>\';
                    html += \'</li>\';
                    gallery_list.append(html);
                });
            }

            // Função para remover imagens
            $(document).on("click", ".remove-gallery-image", function() {
                var image_id = $(this).closest("li").data("id");
                var image_ids = $("#gallery_images").val().split(",");
                var index = image_ids.indexOf(image_id.toString());
                if (index !== -1) {
                    image_ids.splice(index, 1);
                }
                $("#gallery_images").val(image_ids.join(","));
                $(this).closest("li").remove();
            });

            // Habilita a reordenação das imagens com o jQuery UI Sortable
            $("#gallery_images_list").sortable({
                update: function(event, ui) {
                    var image_ids = [];
                    $("#gallery_images_list li").each(function() {
                        image_ids.push($(this).data("id"));
                    });
                    $("#gallery_images").val(image_ids.join(","));
                }
            });
        });
    </script>';
}```

Show images in Front-End:

function display_gallery_images() {
global $post;
$image_ids = get_post_meta($post->ID, ‘gallery_images’, true);

if (!empty($image_ids)) {
    $image_ids = explode(',', $image_ids); // Converte os IDs para um array
    $output = '<div class="gallery-container">';

    foreach ($image_ids as $image_id) {
        $image_url = wp_get_attachment_image_url($image_id, 'full');
        $output .= '<div class="gallery-item"><img src="' . esc_url($image_url) . '" alt="Gallery Image"></div>';
    }

    $output .= '</div>';
    return $output;
}

return '<p>No images found</p>';

}
add_shortcode(‘display_gallery’, ‘display_gallery_images’);


Save and order the images:

// Função para salvar as imagens quando o post for salvo
function save_gallery_images($post_id) {
// Verifica o nonce
if (!isset($_POST[‘custom_metabox_nonce’]) || !wp_verify_nonce($_POST[‘custom_metabox_nonce’], basename(FILE))) {
return $post_id;
}

// Verifica se o post está sendo salvo automaticamente (por exemplo, se for um rascunho)
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
    return $post_id;
}

// Verifica se o usuário tem permissão para editar o post
if ('post' != $_POST['post_type'] || !current_user_can('edit_post', $post_id)) {
    return $post_id;
}

// Verifica se o campo 'gallery_images' foi enviado e salva os valores
if (isset($_POST['gallery_images'])) {
    $gallery_images = sanitize_text_field($_POST['gallery_images']);
    $image_ids = explode(',', $gallery_images);
    
    // Garante que somente IDs válidos sejam salvos
    $valid_image_ids = array_filter($image_ids, function($id) {
        return is_numeric($id) && get_post($id);
    });

    // Atualiza as imagens associadas ao post
    update_post_meta($post_id, 'gallery_images', $valid_image_ids);
}

return $post_id;

}
add_action(‘save_post’, ‘save_gallery_images’);


jQuery UI - Organize the images order:

function load_jquery_ui() {
if (is_admin()) {
wp_enqueue_script(‘jquery-ui-sortable’);
}
}
add_action(‘admin_enqueue_scripts’, ‘load_jquery_ui’);

1 Like