Div neos-contentcollection in frontend

Hello together,

i hope there is a response, the forum seems quite dead currently :frowning:

I’m using a defined (not by me) stylesheet which i include from a external resource and e.g. items inside my Neos.Neos:ContentCollection (also others) are wrapped with the

<div neos-contentcollection></div>

I’ve seen some posts here, but not a solution that works for me.

Isn’t it possible to deactivate the rendering of that div at least in the frontend?

The backend needs this but the frontend does not.

renderer = Neos.Fusion:Case {
	backend {
		condition = ${documentNode.context.inBackend}
		renderer = Neos.Neos:ContentCollection {
			nodePath = "main"
		}
	}
	
	frontend {
		condition = true
		renderer = Neos.Neos:ContentCollectionRenderer {
			@context.node = ${q(node).children('main').get(0)}
		}
	}
}
2 Likes

If you show some of your markup we can help more easily and give some pointers.

Depending on the structure, the div can be turned into something else and simply be used.
Or use the content collection div on some parent level but render its children via a data-attribute into where you need it.

Happy to help, but we would need more details.

2 Likes

Hello together,

thanks a lot for all your input and replies!

I was trying to adapt the code from @mficzel but i was a bit lost where i have to add it to in my code :slight_smile:

I’m using the TwoColums.fusion:

prototype(guide.MP:TwoColumns) < prototype(Neos.Neos:ContentComponent) {
	
    carouselItems = Neos.Neos:ContentCollection {
	
        nodePath = 'carouselitems'
    }
	
	carouselItemNumber = ${q(node).children('carouselitems').children().count()}
	

  renderer = afx`
       <grid>
	     <grid-row>
	        {props.carouselItems}
	      </grid-row>
        </grid>
	`
}

From there i’m renderining the items (pictures) with TwoColumnsItemImage.fusion:

prototype(guide.MP:TwoColumnsItemImage) < prototype(Neos.Neos:ContentComponent) {

    headline = Neos.Neos:Editable {
      property = 'headline'
    }
    caption = Neos.Neos:Editable {
      property = 'caption'
    }
	
    src = Neos.Fusion:Case {
        image {
            condition = ${q(node).property('image') ? true : false}
	        renderer = Neos.Neos:ImageUri {
                asset = ${q(node).property('image')}
            }
        }
        dummyImage {
            renderer = Neos.Fusion:ResourceUri {
                path = 'resource://Neos.Neos/Public/Images/dummy-image.svg'
            }
       }
    }
	
    renderer = afx`
	
	<grid-col mq1="6" mq2="12" mq3="6">
		<div class="padding-s">

			<aspect-ratio ratio="1x1">
				<img src={props.src} alt="" aria-label="" />
			</aspect-ratio>
			<banner-teaser-content class="hydrated">
				<h2 class="banner-teaser-content__heading type-heading-m">{props.headline}</h2>
				<div class="banner-teaser-content__description type-copy">
					<p>{props.caption}</p>
				</div>
			</banner-teaser-content>
		</div>
	</grid-col>`
}

So the rendered site looks like this:

<section>
	<div class="neos-contentcollection">
		<grid class="hydrated">
			<grid-row class="hydrated">
				<div class="neos-contentcollection">
					<grid-col mq1="6" mq2="12" mq3="6">
						<div class="padding-s">
							<aspect-ratio ratio="1x1">
								<div class="aspect-ratio__height-controller">
									<img src="http://roteskreuzguide.de:8081/_Resources/Persistent/a/8/1/5/a815510b3269b56d1c2f00d0a857f93ac883e68a/1_1024x1024.png" alt="" aria-label="" class="aspect-ratio__target">
								</div>
							</aspect-ratio>
							<banner-teaser-content>
								<h2 class="banner-teaser-content__heading type-heading-m">Heading of element 1</h2>
								<div class="banner-teaser-content__description type-copy">
									<p>div of element 1</p>
								</div>
							</banner-teaser-content>
						</div>
					</grid-col>
				
					<grid-col mq1="6" mq2="12" mq3="6">
						<div class="padding-s">
							<aspect-ratio ratio="1x1">
								<div class="aspect-ratio__height-controller">
									<img src="http://roteskreuzguide.de:8081/_Resources/Persistent/f/6/7/6/f676ca0c1807ed4b142f378954e207452b86e418/2_1024x1024.png" alt="" aria-label="" class="aspect-ratio__target">
								</div>
							</aspect-ratio>
							<banner-teaser-content class="hydrated">
								<h2 class="banner-teaser-content__heading type-heading-m">Heading of element 2</h2>
								<div class="banner-teaser-content__description type-copy">
									<p>div of element 2</p></div>
							</banner-teaser-content>
						</div>
					</grid-col>
				</div>
			</grid-row>
		</grid>
	</div>
</section>

The div i would like to have removed is the second <div class="neos-contencollection"></div> you can see in the rendered output, which is coming trough the following (i suppose):

  renderer = afx`
       <grid>
	     <grid-row>
	        {props.carouselItems}
	      </grid-row>
        </grid>

You can make your life way easier by not using a seperate carouselItems collection node and instead allow the carouselItems directly below the content.

In this case this boils down to:

carouselItems = Neos.Neos:ContentCollectionRenderer

1 Like

When using the ContentCollectionRenderer directly you should also add the following lines to the wrapping tag:

data-__neos-insertion-anchor = true
data-__neos-insertion-anchor.@if.onlyRenderInBackend = ${node.context.inBackend && node.context.currentRenderingMode.edit}

This will tell the UI where to insert new elements when using the “insert into” mode.
The same lines are in the ContentCollection prototype.

1 Like

Hey together,

thanks a lot! I was trying to simply change it to:

carouselItems = Neos.Neos:ContentCollectionRenderer

But unfortunately it was with an exception:

An exception was thrown while Neos tried to render your page
The Fusion object "guide.MP:Collection.Content.TwoColumns" cannot be rendered: Most likely you mistyped the prototype name or did not define the Fusion prototype with "prototype(guide.MP:Collection.Content.TwoColumns) < prototype(...)". Other possible reasons are a missing parent-prototype or a missing "@class" annotation for prototypes without parent. It is also possible your Fusion file is not read because of a missing "include:" statement.

root<Neos.Fusion:Case>/ documentType<Neos.Fusion:Matcher>/ element<guide.MP:Document.Page>/ body<guide.MP:Component.Template.Default>/ content<Neos.Fusion:Component>/ main<Neos.Neos:PrimaryContent>/ default<Neos.Fusion:Matcher>/ renderer<Neos.Neos:ContentCollection>/ content<Neos.Neos:ContentCollectionRenderer>/ itemRenderer<Neos.Neos:ContentCase>/ default<Neos.Fusion:Matcher>/ element<guide.MP:TwoColumns>/ renderer<Neos.Fusion:Tag>/ content<Neos.Fusion:Tag>/ content<>/

For a full stacktrace, open Data/Logs/Exceptions/202306140648559f62ec.txt`

It looks like this right now:

prototype(guide.MP:TwoColumns) < prototype(Neos.Neos:ContentComponent) {
	
    carouselItems = Neos.Neos:ContentCollectionRenderer {
	
        nodePath = 'carouselitems'
		data-__neos-insertion-anchor = true
		data-__neos-insertion-anchor.@if.onlyRenderInBackend = ${node.context.inBackend && node.context.currentRenderingMode.edit}
    }
	
	carouselItemNumber = ${q(node).children('carouselitems').children().count()}
	

    renderer = afx`
	<grid>
	  <grid-row>
	    {props.carouselItems}

	  </grid-row>
    </grid>
	`
}

Do i need to define a new:

prototype(mercedesbenz.MP:Collection.Content.TwoColumns) < prototype(Neos.Neos:ContentComponent) { }

?

By not changing it to renderer, and simply adding:

data-__neos-insertion-anchor = true
data-__neos-insertion-anchor.@if.onlyRenderInBackend = ${node.context.inBackend && node.context.currentRenderingMode.edit}

to my ContentCollection, the neos-contentcollection div still remains. I suppose i’m doing something wrong :sweat_smile:

First: The content CollectionRenderer needs a node in the context. So if you are using the carouselitems collection it would be

carouselItems = Neos.Neos:ContentCollectionRenderer {
  @context.node = ${q(node).children('carouselItems').get(0)}
}

This can be skipped if the items are direct children of the TwoColumns (weird naming) element.

That should get you a working render.

Afterwards you have to deal with the needs of the backend to:

  1. Select the collection node to insert stuff. This us done with the contentElementWrapping thing and is the main reason the default rendering is adding the div with metadata. The step is not needed if you have no collection.
  2. Tell the ui where new content are to be placed. That is what the data-__neos-insertion-anchor stuff is for and it would be placed on the <grid-row>
2 Likes

Hey @mficzel!

Thank you a lot! :slight_smile: It worked and i tried it with a new collection i’ve created showing a gallery.

So i was e.g. using this:

    galleryItems = Neos.Neos:ContentCollectionRenderer {
		@context.node = ${q(node).children('galleryItems').get(0)}
    }

to render it later with {props.galleryItems}

Also my mistake was that i had a confusion with camelcase by using carouselitems instead of carouselItems :smiley:

Have a good day! :slight_smile:

3 Likes