0

For a client's website I'm using Elementor to build up the website. The client wants to show photo's of his projects in a Image Carousel.

For this I've created some code to add a meta box to the posts where the images can be added, also I've added a piece of code to create the dynamic tag which makes it possible to connect it to the Image Carousel.

I add the images, I add the dynamic tag, but no images are showing up. In a var_dump I do see the images added to the post.

My question is, what kind of data does the Image Carousel expect to be able to display the images in the carousel?

<?php
/**
 * Theme functions and definitions.
 *
 * For additional information on potential customization options,
 * read the developers' documentation:
 *
 * @package HelloBizChild
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly.
}

define( 'HELLO_BIZ_CHILD_VERSION', '1.0.0' );

/**
 * Load child theme scripts & styles.
 *
 * @return void
 */
function hello_biz_child_scripts_styles() {

    wp_enqueue_style(
        'hello-biz-child-style',
        get_stylesheet_directory_uri() . '/style.css',
        [
            'theme',
        ],
        HELLO_BIZ_CHILD_VERSION
    );
}

add_action( 'wp_enqueue_scripts', 'hello_biz_child_scripts_styles', 20 );

/******************************************************** CUSTOM PHP ******************************************************/
// Voeg een meta box toe alleen aan berichten in de categorie 'project'
add_action('add_meta_boxes', function() {
    global $post;

    if ($post && has_category('project', $post)) {
        add_meta_box(
            'project_images_box',
            'Project Afbeeldingen',
            'project_images_meta_box_callback',
            'post',
            'normal',
            'high'
        );
    }
});

function project_images_meta_box_callback($post) {
    $images = get_post_meta($post->ID, '_project_images', true) ?: [];
    wp_nonce_field('save_project_images', 'project_images_nonce');
    ?>
    <div id="project-images-container">
        <ul id="project-images-list">
            <?php foreach ($images as $image_id): ?>
                <li style="margin-bottom:8px;">
                    <?php echo wp_get_attachment_image($image_id, 'thumbnail'); ?>
                    <input type="hidden" name="project_images[]" value="<?php echo esc_attr($image_id); ?>">
                </li>
            <?php endforeach; ?>
        </ul>
        <button type="button" class="button" id="add-project-image">+ Afbeelding toevoegen</button>
    </div>

    <script>
    jQuery(document).ready(function($){
        var frame;
        $('#add-project-image').on('click', function(e){
            e.preventDefault();
            if(frame){ frame.open(); return; }
            frame = wp.media({
                title: 'Selecteer afbeeldingen',
                button: { text: 'Gebruik deze afbeeldingen' },
                multiple: true
            });
            frame.on('select', function(){
                var attachments = frame.state().get('selection').toJSON();
                attachments.forEach(function(attachment){
                    $('#project-images-list').append(
                        '<li style="margin-bottom:8px;">' +
                        '<img src="'+attachment.sizes.thumbnail.url+'" style="max-width:100px;"/>' +
                        '<input type="hidden" name="project_images[]" value="'+attachment.id+'">' +
                        '</li>'
                    );
                });
            });
            frame.open();
        });
    });
    </script>
    <?php
}

// Sla de afbeeldingen op
add_action('save_post', function($post_id){
    if (!isset($_POST['project_images_nonce']) || !wp_verify_nonce($_POST['project_images_nonce'], 'save_project_images')) return;
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;

    $images = isset($_POST['project_images']) ? array_map('intval', $_POST['project_images']) : [];
    update_post_meta($post_id, '_project_images', $images);
});

// Elementor Dynamic Tag registreren
add_action('elementor/dynamic_tags/register', function($dynamic_tags) {
    $dynamic_tags->register(new \Project_Images_Tag());
});

// Dynamic tag class
/**
 * Project images dynamic tag - robust version
 * Paste into functions.php
 */

if ( did_action( 'elementor/loaded' ) ) {
    add_action('elementor/dynamic_tags/register', function($dynamic_tags) {
        $dynamic_tags->register( new Project_Images_Tag() );
    });
}

/**
 * Dynamic Tag Class
 */
if (!class_exists('Project_Images_Tag')) {
    class Project_Images_Tag extends \Elementor\Core\DynamicTags\Tag {

        public function get_name() {
            return 'project-images';
        }

        public function get_title() {
            return 'Project Afbeeldingen (custom)';
        }

        public function get_group() {
            return 'site';
        }

        public function get_categories() {
            // probeer meerdere constants / fallbacks
            if ( defined('\Elementor\Modules\DynamicTags\Module::GALLERY_CATEGORY') ) {
                return [ \Elementor\Modules\DynamicTags\Module::GALLERY_CATEGORY ];
            } elseif ( defined('\Elementor\Modules\DynamicTags\Module::IMAGE_CATEGORY') ) {
                return [ \Elementor\Modules\DynamicTags\Module::IMAGE_CATEGORY ];
            } elseif ( defined('\Elementor\Modules\DynamicTags\Module::IMAGE_GALLERY_CATEGORY') ) {
                return [ \Elementor\Modules\DynamicTags\Module::IMAGE_GALLERY_CATEGORY ];
            } else {
                return [ 'image' ];
            }
        }

        protected function register_controls() {}

        /**
         * Elementor calls get_value() to retrieve data. 
         * We return multiple possible formats via a single array, but main returned value is an array of associative arrays.
         */
        public function get_value( array $options = [] ) {
            $post_id = get_the_ID();
            if ( ! $post_id ) {
                return [];
            }

            $images = get_post_meta( $post_id, '_project_images', true );

            if ( empty( $images ) || ! is_array( $images ) ) {
                return [];
            }

            // Normaliseer IDs
            $images = array_map( 'intval', $images );
            $gallery_assoc = [];

            foreach ( $images as $image_id ) {
                $full = wp_get_attachment_image_url( $image_id, 'full' );
                $thumb = wp_get_attachment_image_url( $image_id, 'thumbnail' );
                $alt   = get_post_meta( $image_id, '_wp_attachment_image_alt', true );
                $title = get_the_title( $image_id );
                $caption = wp_get_attachment_caption( $image_id );

                $gallery_assoc[] = [
                    'id'      => $image_id,
                    'url'     => $full ?: $thumb,
                    'thumb'   => $thumb,
                    'alt'     => $alt,
                    'title'   => $title,
                    'caption' => $caption,
                ];
            }

            // Return een array van associative arrays — dit is de meest expliciete vorm
            // (sommige Elementor-widgets accepteren ook array van ints of CSV van IDs)
            // Maar we geven ook die extra vormen via keys, zodat debuggen makkelijker is.
            return $gallery_assoc;
        }

        /**
         * Fallback render: als widget direct render() opvraagt, toon niks (of commentaar)
         */
        public function render() {
            // geen echo: widget zal get_value() gebruiken.
            // Houd render kort als fallback (komt zelden voor).
            return;
        }
    }
}


add_action('wp_footer', function() {
    if (is_single()) {
        $meta = get_post_meta(get_the_ID(), '_project_images', true);
        echo '<pre style="background:#111;color:#0f0;padding:10px;">';
        var_dump($meta);
        echo '</pre>';
    }
});

I've contacted Elementor about this, but nobody wants/is able to answer this question, so I'm hoping someone here can.

Thanks in advance!

1
  • Welcome. You need to write your question in English, that includes the comments in your code snippet. Additionally while you think it might be fine to ask customer support questions, this is not possible to handle on SO. There is very little we can do, unless some poor soul drives by that remembers the same martyr and has the magic formula at hand. Please make this a programming question, that is either with the code at hand and/or the API documentation for the parts you are unable to provide the code for. Commented Nov 18 at 17:11

1 Answer 1

0

The issue is that your dynamic tag is using the wrong category and data format for Elementor's Image Carousel widget.

The Problem:

Your get_categories() method has multiple fallbacks that might return IMAGE_CATEGORY (for single images) instead of GALLERY_CATEGORY (for galleries/carousels). Also, Elementor's gallery widgets expect a specific array format.

The Solution:

Update these two methods in your Project_Images_Tag class:


public function get_categories() {
    // Explicitly return GALLERY_CATEGORY for carousel/gallery widgets
    return [ \Elementor\Modules\DynamicTags\Module::GALLERY_CATEGORY ];
}

public function get_value( array $options = [] ) {
    $post_id = get_the_ID();
    if ( ! $post_id ) {
        return [];
    }

    $images = get_post_meta( $post_id, '_project_images', true );

    if ( empty( $images ) || ! is_array( $images ) ) {
        return [];
    }

    // Return array format that Elementor gallery widgets expect
    $gallery = [];
    foreach ( array_map( 'intval', $images ) as $image_id ) {
        $gallery[] = [
            'id' => $image_id,
        ];
    }

    return $gallery;
}

Why this works:

Elementor's Image Carousel expects dynamic tags from the GALLERY_CATEGORY that return an array of arrays with 'id' keys: [['id' => 123], ['id' => 456]]. Elementor then handles fetching the URLs and thumbnails internally.

After updating:

  1. Clear Elementor cache (Elementor > Tools > Regenerate CSS)

  2. Refresh your editor

  3. Your dynamic tag should now appear and work correctly in the Image Carousel

Hope this helps!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.