[SOLVED] Sidebar parent inheritance

Hi guys,

I want a sidebar that have sidebar elements.

'TYPO3.Neos.NodeTypes:Page':
  childNodes:
    'sidebar':
      type: 'TYPO3.Neos:ContentCollection'
      constraints:
        nodeTypes:
          '*': false
          'XY:SidebarElement': true
sidebar = TYPO3.Neos:ContentCollection {
    nodePath = 'sidebar'
    collection = ${q(site).children('sidebar').children()}
}

Now the question. How can I get all sidebar-elements from all parten nodes (Documents) and the current node (Document)?

My first try was:

${q(site).parents().children('sidebar')}

Greetings =)

PS: Thanks! ! !

Try something like this.

${q(documentNode).parents().children('sidebar').children().get()}

The two misconceptions i see in your code is that you start traversing at the site node and that you access the “sidebar” collection but not the content inside.

1 Like

Thanks a lot! But this query does not fetch the current document sidebar elements.

And if I set this query as new collection in TS. The sidebar wont display this collection.

sidebar = TYPO3.Neos:ContentCollection {
    nodePath = 'sidebar'
    collection = ${q(documentNode).parents().children('sidebar').children().get()}
}

The debug output shows 2 sidebar elements.

${q(documentNode).parents().children('sidebar').children().filter('[showOnChilds = true]').add(q(documentNode).children('sidebar').children())}

this query works for me.

But how can I overwrite the collection of the sidebar?

Not entirely sure what you want to achieve. Do you mean traversing up until you find the first document that has sidebar items?

For that you can use a recursive fusion-definition:

prototype(Vendor.Site:SitebarItemAggregator) < prototype(TYPO3.TypoScript:Case) {
     currentDocumentHasSidebarItems {
        condition = ${q(documentNode).children('sidebar').children().count() > 0}
        renderer =  ${q(documentNode).children('sidebar').children().get()}
     }

     currentDocumentHasAParentDocument { 
        condition  = ${q(documentNode).parent().is('[Instanceof TYPO3.Neos:Document]')}
        renderer = Vendor.Site:SitebarItemAggregator
        renderer.@context.documentNode =  ${q(documentNode).parent().get(0)}
     }
    
     fallbackToEmptyArray {
        condition = ${true}
        renderer = ${[]}
     } 
}

You can use that in your Collection like this.

sidebar = TYPO3.TypoScript:Collection {
   collection = Vendor.Site:SitebarItemAggregator
   ...
}

Beware that this is untested code i have just written down. You will have to adjust it. Also be warned that this makes the rendering of the sidebar depending on all parent nodes. You will have to adjust the caching to invalidate caches properly if a sidebar item in a parent node is changed.

I want to achieve that the child-items expand the sidebar with their own elements without removing the elements from the parent-items.

Example:

Root-Sidebar

  • Lorem
  • Ipsum

Parent1-Sidebar

  • Lorem
  • Ipsum
  • Parent1-Element

Parent1-Child1-Sidebar

  • Lorem
  • Ipsum
  • Parent1-Element
  • Child1-Element

In that case render two items into the sidebar.

  1. sidebar items of parent pages but not current one into a TYPO3.TypoScript:Collection
  2. current sitebar collection an TYPO3.Neos:PrimaryContent

You probably will have to disable ContentElementWrapping in the first collection to avoid editing nodes from another document.

It will also help the editors to give some visual hint in the backend where the inherited content ends.

Thanks for your greate help.

sidebar = TYPO3.Neos:ContentCollection {
    nodePath = 'sidebar'
    collection = ${q(documentNode).parents().children('sidebar').children().filter('[showOnChilds = true]').add(q(documentNode).children('sidebar').children()).get()}
    @cache.mode = 'uncached'
    @cache.context = ${q(documentNode)}
}

this flow query works for me:

${q(documentNode).parents().children('sidebar').children().filter('[showOnChilds = true]').add(q(documentNode).children('sidebar').children()).get()}

But in my sidebar only the elements who was created on this page are shown. I have no idea why.

How can I achive that? Should I check it in the SidebarElement template?

PS: @mficzel thanks again! You are my hero!

I suggest to play it like this

sidebar = TYPO3.TypoScript:Array {

    // inherited items that are shown but are not editable in be
    beHintForInheritedItems = TYPO3.TypoScript:Tag {
       content = 'sidenbar items from parent documents'
       @if.showHintOnlyInBackend = ${documentNode.context.inBackend}
    }
    inheritedItems = TYPO3.Neos:ContentCollection {
       ... 
       // avoid selecting and editing of content in this collection here
       prototype(TYPO3.Neos:Content) {
          @process.contentElementWrapping > 
       }
       // avoid selecting this collection
       @process.contentElementWrapping >
    }

    // local items editable in backend
    beHintForLocalItems = TYPO3.TypoScript:Tag {
       content = 'sidenbar items of this document'
       @if.showHintOnlyInBackend = ${documentNode.context.inBackend}
    }
    localItems = TYPO3.Neos:PrimaryContent{
       ...
    }
}

Note: @process.contentElementWrapping is a processor that adds metadata for the backend to the HTML output.

1 Like

Thanks! This works for me:

prototype(XY:xy:SidebarItemArray) < prototype(TYPO3.TypoScript:Array) {
    // inherited items that are shown but are not editable in be
    beHintForInheritedItems = TYPO3.TypoScript:Tag {
       tagName = 'p'
       content = 'sidenbar items from parent documents'
       @if.showHintOnlyInBackend = ${documentNode.context.inBackend}
    }
    inheritedItems = TYPO3.Neos:ContentCollection {
       nodePath = 'sidebar'
       content.collection = ${q(documentNode).parents().children('sidebar').children().filter('[showOnChilds = true]').get()}
       // avoid selecting and editing of content in this collection here
       prototype  = TYPO3.Neos:Content {
          @process.contentElementWrapping > 
       }
       // avoid selecting this collection
       @process.contentElementWrapping >
    }

    // local items editable in backend
    beHintForLocalItems = TYPO3.TypoScript:Tag {
       tagName = 'p'
       content = 'sidenbar items of this document'
       @if.showHintOnlyInBackend = ${documentNode.context.inBackend}
    }
    localItems = TYPO3.Neos:ContentCollection {
       nodePath = 'sidebar'
       content.collection = ${q(documentNode).children('sidebar').children().get()}
    }
}

But how can I disable editing sidebarelements child nodes?

prototype(XY.xy:SidebarElement) < prototype(TYPO3.Neos:Content) {
    templatePath = 'resource://XY.xy/Private/Templates/TypoScriptObjects/SidebarElement.html'
    headline = ${q(node).property('headline')}
    isInherited = ${q(documentNode).is(q(node).closest('[instanceof TYPO3.Neos:Document]').get(0))}

    maincontent = TYPO3.Neos:ContentCollection {
        nodePath = 'maincontent'
    }
}

I found an error in my example.

inheritedItems = TYPO3.Neos:ContentCollection {
   ...
   ## this was wrong: prototype  = TYPO3.Neos:Content 
   prototype(TYPO3.Neos:Content) {
      @process.contentElementWrapping > 
   }
}
1 Like

Now I understand the complete example :smiley:

I added

   prototype(TYPO3.Neos:ContentCollection) {
      @process.contentElementWrapping > 
   }

now it works =)

Thanks a lot! ! !

1 Like