Skip to content
● Grav 2.2 is out: 2x faster cold starts and 96% less memory on big sites. Read the announcement →

Render thumbnail in Flex object list view

field

Started by gravinator 1 month ago · 4 replies · 440 views
1 month ago

I'm creating a blog based on the flex objects with the following fields:

YAML
 admin:
    menu:
      list:                
        title: News
        icon: fa-newspaper-o
    list:
      fields:
        published:
          field:
            type: toggle
            label: Active
          width: 5
        news_title:
          field:
            label: Name
          link: edit
        news_date:
          field:
            label: Date
            type: datetime
        news_image:
          field:
            type: field
            label: Photo

All the columns renders except the photo - which shows [object Object].

Is there any way to render object as image (preferable thumbnail)?

last edited 09/04/26 by gravinator
1 month ago

Field is file (I tried thumbnail in as seen in some examples)

4 weeks ago

I'd also like to know how to display images in the Flex Objects list view within the Admin2 plugin.

According to the official docs, we can build a custom admin page, but building and maintaining full-featured UI components from scratch is quite difficult.

https://learn.getgrav.org/20/api/developer-guide#custom-admin-pages

If there's a way to configure image previews in the standard Admin2 list view via blueprints, I'd really appreciate it if someone could share how to do it.

5 days ago

Hello!
I created a thumbnail list on a custom admin page. You can navigate to it from the sidebar and view a list of thumbnails. Clicking a thumbnail takes you to the editing page for that object.
Since it's not a full-featured UI (no search, sorting, or pagination), you'll need to configure it using the options in the fetch method.

PHP
use RocketTheme\Toolbox\Event\Event;
(...)
    public function onApiSidebarItems(Event $event): void
    {
        $items = $event['items'] ?? [];
        $items[] = [
            'id'       => 'news',
            'plugin'   => 'news',
            'label'    => 'My Custom Thumbnail List',
            'icon'     => 'fa-newspaper-o',
            'route'    => '/plugin/news',
        ];
        $event['items'] = $items;
    }
    public function onApiPluginPageInfo(Event $event): void
    {
        if ($event['plugin'] !== 'news') {
            return;
        }

        $event['definition'] = [
            'id'        => 'news',
            'plugin'    => 'news',
            'title'     => 'My Custom Thumbnail List',
            'icon'      => 'fa-newspaper-o',
            'page_type' => 'component',
        ];
    }
JS
// user/plugins/news/admin-next/pages/news.js
const TAG = window.__GRAV_PAGE_TAG
customElements.define(TAG, class extends HTMLElement {
    async connectedCallback() {
        const root = this.attachShadow({ mode: 'open' });
        root.innerHTML = '<div>Loading...</div>'

        try {
            const baseUrl = window.__GRAV_API_SERVER_URL || '';
            const prefix = window.__GRAV_API_PREFIX || '';
            const token = window.__GRAV_API_TOKEN || '';
            const type = 'news';

            const endpoint = `${baseUrl}${prefix}/flex-objects/${type}`;

            const response = await fetch(endpoint, {
                method: 'GET',
                headers: {
                  'Accept': 'application/json',
                  'X-API-Token': token,
                }
            });

            if (!response.ok) {
                throw new Error(`API error: ${response.status} ${response.statusText}`);
            }

            const res = await response.json();
            const items = res.data || [];

            root.innerHTML = '<div id="grid" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(120px, 1fr));"></div>'
            const gridEl = root.querySelector("#grid");
            items.forEach(item => {
                const newsImage = item.news_image;
                if (!newsImage || typeof newsImage !== 'object') {
                    return;
                }
                const images = Object.values(newsImage)
                if (images.length === 0) {
                    return;
                }
                const imagePath = `${baseUrl}/user/data/${type}/${item.key}/${images[0].path}`;
                const a = document.createElement('a');
                const editUrl = `${baseUrl}${window.__GRAV_ADMIN_BASE}/flex-objects/${type}/${item.key}`;
                a.href = editUrl;
                a.addEventListener('click', e => {
                    e.preventDefault();
                    window.__GRAV_NAVIGATE(editUrl);
                });
                const img = document.createElement('img');
                img.src = imagePath;
                img.style.width = '120px';
                img.style.height = 'auto';
                a.appendChild(img);
                gridEl.appendChild(a);
            });

        } catch (error) {
            window.__GRAV_TOAST.error('Failed to load news list');
        }
    }
});

Suggested topics

Topic Participants Replies Views Activity
Support · by stell, 7 days ago
4 235 5 days ago
Support · by Gravver, 2 weeks ago
6 278 1 week ago
Support · by Marcel, 4 weeks ago
2 337 1 week ago
Support · by blu3prince, 2 weeks ago
1 251 2 weeks ago
Support · by complanar, 3 weeks ago
6 330 2 weeks ago