1
votes

I have such page structure (Typo3 v10):

Page 1
- Page 1.1
- Page 1.2
- - Page 1.2.1
...
Page 2
- Page 2.1
- Page 2.2
...

I need to show an image (from page resources) with sliding feature. So I use this code:

lib.banner = FILES
lib.banner {
    references {
        table = pages
        data = levelmedia: -1, slide
    }
    renderObj = IMAGE
    renderObj {
        file.import.data = file:current:uid
        file.treatIdAsReference = 1
        wrap = <div class="banner">|</div>
    }
}

In HTML template I use it as follow:

<f:cObject typoscriptObjectPath="lib.banner" />

Everything works nice. I see the image from CURRENT page resources or from the CURRENT page's parents resources.

Now If I need to show the image from other page with special id I use the following code

lib.banner = FILES
lib.banner {
    references {
        table = pages
        uid.data = field:PageIdParam
        fieldName = media
    }
    renderObj = IMAGE
    renderObj {
        file.import.data = file:current:uid
        file.treatIdAsReference = 1
        wrap = <div class="banner">|</div>
    }
}

In HTML:

<f:cObject typoscriptObjectPath="lib.banner" data="{ PageIdParam: 123 } />

But what if I need to add sliding feature?

I try to use the following code:

lib.banner = FILES
lib.banner {
    references {
        table = pages
        data = levelmedia: -1, slide
        uid.data = field:PageIdParam
        fieldName = media
    }
    renderObj = IMAGE
    renderObj {
        file.import.data = file:current:uid
        file.treatIdAsReference = 1
        wrap = <div class="banner">|</div>
    }
}

Unfortunately it stop working.. what I do wrong?

I also tried to play around with file.import.data = levelmedia:-1, slide, but did not help

UPDATE:

More detailed info with explanation why I need this:

I created a custom content element (according to https://docs.typo3.org/m/typo3/reference-coreapi/master/en-us/ApiOverview/ContentElements/AddingYourOwnContentElements.html)

Custom content element with Pages field

The element outputs the list of images. Images are taken from the pages.

Typoscript for the content element:

tt_content {
    images_from_pages =< lib.contentElement
    images_from_pages {
        templateName = ImagesFromPages
        dataProcessing {
            30 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
            30 {
                special = list
                special.value.field = pages
                maxItems = 100
                as = contentElementPages
                titleField = nav_title // title

                dataProcessing {
                    10 = TYPO3\CMS\Frontend\DataProcessing\FilesProcessor
                    10 {
                        references.fieldName = media
                    }
                }
            }
        }
    }
}

To output the images I used the fluid template:

<html data-namespace-typo3-fluid="true" xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers">

<f:if condition="{contentElementPages}">
    <f:for each="{contentElementPages}" as="page">
        <h2>{page.title}</h2>
        <f:if condition="{page.files.0} ">
            <f:then>
                <f:render partial="ImagesFromPages/Image" arguments="{file: page.files.0}" />
            </f:then>
            <f:else>
                <f:cObject
                    typoscriptObjectPath="lib.banner"
                    data="{
                        parentPageId: page.data.pid,
                        width: '300c',
                        height: '300c'
                    }"
                />
            </f:else>
        </f:if>
    </f:for>
</f:if>

</html>

So as a result I have a list of [page1 title / img1, page2 title / img2 ...]

In case if the page in the cycle has no image, I use page.data.pid to reference the "parent page"

The problem I could not solve yet: if the parent page has no image as well, I need to output the image of parent of parent recursively (sliding).

I know, I could use "default image or image from root page", but first I would like to try to get the image from "parent of parent page"

2
"Unfortunately it stop working" showing us several parts of more or less random config code and templates doesn't allow us to even try to guess what's wrong. The very first thing you have to do is going to the inspector tool of your browser and check if there are any errors displayed in the console, and try to fix them if possible. If won't work still, copy the whole page's source code, save it as a static HTML in root folder of your project, and try to find the bugs, fix them and then move changes into your configs. If it is published, show us the link. - biesior
Another approach is using the custom plugin, or the Mask extension it allows build such widgets as galleries, carousels, and others just with preparing structure in GUI editor, and optionally modifying generated Fluid template(s). TBH, for many years I prefer this way instead of struggling with TS. Additionally, Mask generates TCEform for such structures, so it's easier to choose a source of images to display for admins, who don't know how to edit TS. - biesior
I mean that first 2 snippets shows <div class="banner"><img ..></div> the last snippet shows <div class="banner"></div> - June
Just to make sure, have you got proper coun of images in desired destination, as far as I can see you're using media field of pages table, did you 3 images there? - biesior
Yes, I uploaded images into all pages I'm testing with - June

2 Answers

0
votes

just to recapture your problem:

You have images assigned to pages which are inherited. If a page has not assigned an image the parents are consulted until there is an image.
This mechanism works in TYPO3 with levelfields as long is the current page is considered.

There is no build in mechanism in typoscript if you want to access data from another page (given by an uid)

If you need the image for any other page (e.g. for teaser) you need to use PHP to compute the image from the rootline of that page. Build a userfunc or viewhelper if you use FLUID anyway.

Or you build up a cascaded typoscript with a lot of .ifEmpty elements where you request the parent, parent of parent, parent of parent of parent, ... whether there is an image.
This would be a manual recursion as you need to copy the code for all possible levels by hand (and adapt the determining of the uid of the page in question). Therefore I recommend to use PHP.

0
votes

What's the reason for using the value hardcoded in the Fluid template instead of using it directly in TypoScript? That works and can be easily overridden with TS for selected pages if needed like in ext-ts: lib.banner.references.uid = 789 (where 123 and 789 are uids of required page, from which media's field images should be taken):

Tested and working sample (actually it is the same as your first version, just):

lib.banner {
    references {
        table = pages
        uid = 123
        fieldName = media
    }
    renderObj = IMAGE
    renderObj {
        file.import.data = file:current:uid
        file.treatIdAsReference = 1
        wrap = <div class="banner">|</div>
    }
}

For sliding issue

Keep in mind, that slide is placed in relative parent-child context, and combining static uid with slide may produce weird results.

In general slide accepts just two values it's -1 and 2, and both refers to page tree's traversing.

This sample works as expected, it will use media of the current page and if not present will traverse the tree up to the root looking for them.

Note: as levelmedia already points to the media field, don't need to use fieldName again, the rest of the code remains unchanged

references {
    table = pages
    data = levelmedia: -1, slide
}

Last edit

Your update to the question changes things totally, now it seems to me that you want to display images from the first page that you selected in your CE. That is not a job for TS slide, instead you should use custom PHP to check these pages and select images from the first one containing any images. Below there's a sample code of the FE plugin that does that, note, that's just a POC and may require fixing. If this is what you want, I can publish the complete extension on Github, so you can test it.

plugin's action:

public function listAction()
{

    /** @var FileRepository $fileRepo */
    $fileRepo = GeneralUtility::makeInstance(FileRepository::class);
    $fileObjects = [];

    $pidList = $this->configurationManager->getConfiguration(
        ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK
    )['persistence']['storagePid'];

    $pids = GeneralUtility::trimExplode(',', $pidList, true);

    $mediaFound = false;
    foreach ($pids as $pid) {
        if ($mediaFound) continue;
        $fileObjects = $fileRepo->findByRelation('pages', 'media', $pid);
        if (count($fileObjects) > 0) {
            $mediaFound = true;
        }
    }

    $this->view->assign('files', $fileObjects);

}

action's view

<f:for each="{files}" as="file">
    <f:image src="{file.uid}" treatIdAsReference="1"/>
</f:for>