Rendering a content element of another page?

Hi,

I have two types of pages.

  1. A “source” page (TestimonialPage) with a ContentCollection that holds a custom TeaserElement, and
  2. a “destination” page with a LinkEditor, to choose the sourcePage.
    The link goes to the page property: testimonial. That works fine.
    Both pages have the same ContentCollection (teaserCollection).

The aim is to render the Teaser from the source page into the ContentCollection of the destination page.

testimonialPage < page

testimonialPage.body {
	templatePath = 'resource://Eg.Website/Private/Templates/Page/TestimonialPage.html'
	teaserCollection = ContentCollection {
		nodePath = 'teaserCollection'
	}
}

teaserPage < page

teaserPage.body {
	templatePath = 'resource://Eg.Website/Private/Templates/Page/TestimonialPage.html'
	teaserCollection = ContentCollection {
		testimonial = ${q(node).property('testimonial')}
		rootNode = ${q(node).parents().last()}
		nodePath = ${q(rootNode).find(this.testimonial).find('teaserCollection').property('_path')}
		collection = ${q(rootNode).find(this.testimonial).find('teaserCollection').children()}
	}
}

The property testimonial holds the value (f:debug):
'testimonial' (11) => 'node://d0e45856-e0a5-41c7-a351-812a6fb5b035' (43)

First i tried ${q(site) … than a lot of other things.

  1. Has anybody the “magic lines”, that do the trick?
  2. Does anybody know how to debug (print, echo …) TypoScript / Eel

chears
Klaus

Hi,

see http://neos.readthedocs.io/en/stable/References/ViewHelpers/TypoScript.html?highlight=context in combination with http://neos.readthedocs.io/en/stable/CreatingASite/RenderingCustomMarkup/CustomContentElements.html?highlight=context=%22{node

###1:

Maybe you will find the magic lines in follow :wink::
Works well for me. Maybe you will find one or two possible improvements here and there.

#NodeTypes.MixinSmarterLink.yaml

#Use it within other NodeTypes with 
#superTypes:
# ' Vendor.Site:MixinSmarterLink' = TRUE

### MixinSmarterLink


'Vendor.Site:MixinSmarterLink':
  abstract: TRUE
  superTypes:
    'TYPO3.Neos:Content': TRUE
  ui:
    inspector:
      groups:
        yourGroupName:
          label: yourGroupName
          position: 4
  properties:
    link:
      type: string
      ui:
        label: 'Link zu anderem Element/Node'
        help:
          message: "NodeElement zu dem ein Link erstellt werden soll."
        inspector:
          group: 'yourGroupName'
          editor: 'TYPO3.Neos/Inspector/Editors/LinkEditor'
          editorOptions:
            placeholder: 'Link direkt einfügen, oder nach Node suchen'
         position: 103
#SmarterCollector.ts2

### SmarterCollector to use nodeContent in other Neos-places
prototype(Vendor.Site:SmarterCollector) < prototype(TYPO3.Neos:Content) {

    CCRenderer = TYPO3.Neos:ContentCollectionRenderer

    linkedNode = ${q(node).property('link')}
    linkedNode.@process.removeProtocolPrefix = ${String.pregReplace(value, "/node:\/\//" , '')}
    linkedNode.@process.findByIdentifier = ${q(node).find('#' + value)}
    linkedNode.@process.getContainer = ${value.children('container').get(0)}
}

Should do with first line change to:

linkedNode = ${q(node).property('testimonial')}

Last Line you will have to change to:

linkedNode.@process.getTeaserCollection = ${value.children('teaserCollection').get(0)}

Or something like this.

At the End Fluid-Template:

# SmarterCollector.html

{namespace ts=TYPO3\TypoScript\ViewHelpers}
<ts:render path="CCRenderer" context="{node: linkedNode}" />

###2:

I’m quite sure there are NO tools or other things [quote=“energyWinner, post:1, topic:1262”]
to debug (print, echo …) TypoScript / Eel
[/quote]
, except your known
<f:debug>{whatIsInThisProperty}</f:debug>

Because I ask for this a few times in Forum and somewhere else. Nowhere I got an answer …

Hope at least «1:» will help
Cheers Martin

Hi Martin,

thanks a lot for your reply.
Seems to be very complicated.
I will check it on monday. Maybe I’ll ask you some additional questions.

For debugging Eel I use the TypoScript Value object and f:debug.
Discovered this today:

Put this inside your page TS-Object

	debugString = TYPO3.TypoScript:Value {
		value = ${q(node).children('teasercollection').property('_path')}
	}

And this in your Fluid template:

	<f:if condition="{debugString}">
		{debugString -> f:debug(title: 'TsValue:debugString')}
	</f:if>

It’s not perfect, but it helps debugging that flowQuery stuff …

Have a nice weekend!
Klaus

Hi Klaus,
the «MixinSmarterLink» NodeType is only the abstraction Layer I use.

With change in first and last Line I wrote above - I guess, you don’t have to use my MixinSmarterLink.yaml.
So you can use your direct declared property «teaserCollection» or the «destination» (
In the end, just the property with LinkEditor defined) from:[quote=“energyWinner, post:1, topic:1262”]
2. a “destination” page with a LinkEditor, to choose the sourcePage.
[/quote]

My code and the Mixin is only a copy & paste from working code.


If the ts2 looks complicated. It’s only a problem for Neos (if I’m not completely wrong: No uri/link from neos-link.node ViewHepler with node-identifier (Paths must not contain two consecutive slashes.)) to find nodes with the «node://» in front. So

  • the pregReplace only delete this «node://».
  • the findByINdentifier call an find() with «#» in front of the identifierHash.
  • the getContainer/getTeaserCollection only go to children with this pathName.

###Debug

I will give a try, but at first glance your code could be the almost same like:

#.ts2-file 
value = ${q(node).children('teasercollection').property('_path')}

#fluidTemplate-file
<f:debug title="valueFrom_teaserCollection_Path">{value}</f:debug>

If no big different: This code would be easier to read, I think. But I have to tryout the differences first.

Same nice and sunny weekend for you!

Later on…
Now I see: Maybe It’s the different places, we use our code.
You in page TS-Object [quote=“energyWinner, post:4, topic:1262”]
Put this inside your page TS-Object
[/quote]
I use it in the Prototype from SmarterCollector…

Hi Martin,

thank you for detailed explanaition. I will implement it on monday morning!
I just don’t thought, it would be neccessary to convert such things by hand.

By
Klaus

@mad why you don’t use property type reference instead of string for your node property ‘link’? Just a hint for loving neos more;-)

1 Like

If you are going to link to internal pages only, using the reference type is preferred as it gives you the node directly (which can then be used in the template with the link.node VH). If you use the link editor to create arbitrary links the easiest way to convert them is:

link.@process.convertToUri = TYPO3.Neos:ConvertUris

Then link will contain the url directly.

@miegli
Sounds lovely :heart_eyes:: Thanks.

@christianm
Every day a new day to learn new stuff and forget what I have learned. thanks for reminder.


Use of «References» for internalLinks only is much more interesting. Thanks for hints!

But to work with, seems to be different. Did someone know how I get the child “container” from the chosen site? I can’t use any FlowQuery Operation.

With reference (definition further down) and

### SmarterCollector to use nodeContent in other Neos-places
prototype(Vendor.Site:SmarterCollector) < prototype(TYPO3.Neos:Content) {
    
    CCRenderer = TYPO3.Neos:ContentCollectionRenderer

    linkedNode = ${q(node).property('internalLink')}
    linkedNode.@process.GetContainer = ${value.children('container')}

Also with ${q(node).property('internalLink').children('container')}
I get the error
Method “children” is not callable in untrusted context

With ${q(node).property('internalLink').get(0)}
I get the error
Method “get” is not callable in untrusted context


property-Definition:

##
# MixinSmarterInternalLink for internal (ONLY) links to other NEOS-nodeTypes
##

'Vendor.Site:MixinSmarterInternalLink':
  abstract: TRUE
  superTypes:
    'TYPO3.Neos:Content': TRUE
  ui:
    inspector:
      groups:
        yourGroup:
          label: yourGroup
          position: 4
  properties:
    internalLink:


Maybe there is a docu or tut about «what is untrusted context in Neos and how to get rid of»?

Sound counterintuitive, but the property operation used in q(node).property('internalLink') will return the raw value (a node) and no longer a FlowQuery object so in the second try (with get(0)) that can be skipped. And for using the children operation you need to wrap that again in FlowQuery like this q(q(node).property('internalLink')).children('container').get(0) to get the child node “container” from your internalLink node.

@christianm
Thanks, works good. And I know the counterintuitive (I guess). But I use it in the NeedMoreSpeed situation.

  • With «find the children» I concat the value in the «container»-Node only. So I can display this separated nodes in the Backend-Editing-Area (each root-node) correctly.
  • On the other hand the needed div-wrapper I use for (display nodes split in Backend), does not harm the layout in the resulting frontend-output …

I know it sounds complicated and counterintuitive but I can’t find an other working and passably-speedy solution.
If you see a simplification in logic or solution-implementation, I very welcome hints and suggestions.