Problem
Given two NodeTypes, Timeline and TimelineEvent. Timeline is both Content
and ContentCollection
. When inserting a TimelineEvent
into Timeline
the position in the DOM is wrong. The screenshot shows the new TimelineEvent
(the <li>
tag), the arrow where it should have been placed:
That happens, because the element is wrapped and the UI inserts the new content directly into it. Not quite as expected in this particular case, but as implemented. So not really a bug…
Trying to fix it–or at least find a workaround
-
Tried it like described in this blog post by @sebobo, but that doesn’t help (even though AFX looks way better.) It works for that case, because new children are actually supposed to be inserted directly into the element. For my case, the same problem exists.
-
Then I came up with this fix, actually using a
ContentCollection
for the items:diff --git a/DistributionPackages/Foo.Bar.Base/Resources/Private/Fusion/NodeTypes/Timeline.fusion b/DistributionPackages/Foo.Bar.Base/Resources/Private/Fusion/NodeTypes/Timeline.fusion index db91a1a1..6635979f 100644 --- a/DistributionPackages/Foo.Bar.Base/Resources/Private/Fusion/NodeTypes/Timeline.fusion +++ b/DistributionPackages/Foo.Bar.Base/Resources/Private/Fusion/NodeTypes/Timeline.fusion @@ -2,7 +2,8 @@ prototype(Foo.Bar.Base:Timeline) < prototype(Neos.Neos:Content) { templatePath = 'resource://Foo.Bar.Base/Private/Templates/NodeTypes/Timeline.html' title = ${q(node).property('title')} - items = Neos.Fusion:Collection { + items = Neos.Neos:ContentCollection { + tagName = 'ul' collection = ${q(node).children().get()} itemName = 'node' itemRenderer = Foo.Bar.Base:TimelineItem diff --git a/DistributionPackages/Foo.Bar.Base/Resources/Private/Templates/NodeTypes/Timeline.html b/DistributionPackages/Foo.Bar.Base/Resources/Private/Templates/NodeTypes/Timeline.html index 2812e43a..dd5df866 100644 --- a/DistributionPackages/Foo.Bar.Base/Resources/Private/Templates/NodeTypes/Timeline.html +++ b/DistributionPackages/Foo.Bar.Base/Resources/Private/Templates/NodeTypes/Timeline.html @@ -7,9 +7,7 @@ {neos:contentElement.editable(property: 'title', tag: 'h2')} </div> - <ul> - {items -> f:format.raw()} - </ul> + {items -> f:format.raw()} </div> </div>
Now when clicking the plus icon on the toolbar of the “inner” collection, all works fine, but there is still the “outer” wrapping around the whole element, and if inserting a
TimelineItem
using that, it still ends up at the same wrong place. -
This is what I came up with next, after some time and a finding a hint by @mficzel in this discuss post:
prototype(Foo.Bar.Base:Timeline) < prototype(Neos.Neos:Content) { // … @process.contentElementWrapping > } // and add contentElementWrapping.wrap around the Timeline title // in the template to make that work.
Beautifully solves the problem! Except… now when inserting a
Timeline
element, the returned HTML has no “outer” wrapping anymore, and only the first “inner” wrapping around the title is seen by the UI and added to the DOM of the document. As a result the rendering is broken and addedTimelineItem
nodes do not show up, unless the document is reloaded.
Summary: No way to solve the issue right now.
A possible real solution
Somehow we need to wrap the whole element and specify where new children are supposed to be added in the DOM. This is a rough sketch of a way to do that, as braindumped during a discussion with @christianm today:
prototype(Foo.Bar.Base:Timeline) < prototype(Neos.Neos:Content) {
// …
// Disable the direct insertion of children on the outer wrapping
@process.contentElementWrapping.insertionPoint = false
items = Neos.Fusion:Collection {
tagName = 'ul'
nodePath = '.'
// Add a new lightweight wrapper where insertion _should_ take place
@process.contentCollectionWrapping = Neos.Neos:ContentCollectionWrapping
}
}
This would be backwards-compatible. Now it only needs to be implemented…