Benjamin
(Benjamin A)
August 30, 2023, 7:48am
1
Hello together,
i’m posting here because i’m struggling about to implement a working Pagination for the Blog of Neos.Demo. All in all, Flowpack.Listable is working perfectly fine with my own little created NodeTypes and i can list them, create Paginations and so on.
So i’ve tried to List some elements of BlogPostingList.fusion . Well, i’ve also tried to list Neos.Demo:Document.Blog
and Neos.Demo:Document.BlogPosting
, but because of the current encapsulation by using Cards/Container i’m not sure how to actually get any news and it wasn’t working anyway
So what i thought is implementing a own BlogPostingList.fusion, as this element is already creating a list.
##
# "ListableBlogList" element
#
prototype(Neos.Demo:Content.ListableBlogList) < prototype(Flowpack.Listable:PaginatedCollection) {
collection = ${q(site).find('[instanceof Neos.Demo:Content.BlogPostingList]').get()}
itemsPerPage = 1
maximumNumberOfLinks = 2
listRenderer = 'Flowpack.Listable:Collection'
showPreviousNextLinks = true
}
##
# "BlogPostingList" element
#
prototype(Neos.Demo:Content.BlogPostingList) < prototype(Neos.Neos:ContentComponent) {
blogArticles.@if.has = ${q(node).property('blogs')}
blogArticles = ${q(q(node).property('blogs')).children('[instanceof Neos.Demo:Document.BlogPosting]')}
blogArticles.@process.sortBy = ${value.sort("datePublished", "DESC")}
blogArticles.@process.limit = ${value.slice(0, q(node).property('limit'))}
renderer = Neos.Demo:Presentation.Cards.Container {
content = Neos.Fusion:Loop {
items = ${props.blogArticles}
itemName = "blogPosting"
itemRenderer = Neos.Demo:Presentation.Cards.Card {
imageUri = Neos.Neos:ImageUri {
asset = ${q(blogPosting).property('image')}
maximumWidth = 400
maximumHeight = 225
}
title = ${q(blogPosting).property('title')}
content = ${q(blogPosting).property('abstract')}
uri = Neos.Neos:NodeUri {
node = ${blogPosting}
}
}
}
}
@cache {
mode = "cached"
entryIdentifier {
node = ${node}
}
entryTags {
# invalidate cache when the node rendered changes
1 = ${Neos.Caching.nodeTag(node)}
# invalidate cache when one of the selected blogs changes (might become hidden)
2 = ${Neos.Caching.nodeTag(q(node).property('blogs'))}
# invalidate cache when a descendent of the selected blogs changes
3 = ${Neos.Caching.descendantOfTag(q(node).property('blogs'))}
}
}
}
##
# "BlogPostingList" element for Flowpack.Listable
#
prototype(Neos.Demo:Content.BlogPostingList.Short) < prototype(Neos.Neos:ContentComponent) {
blogArticles.@if.has = ${q(node).property('blogs')}
blogArticles = ${q(q(node).property('blogs')).children('[instanceof Neos.Demo:Document.BlogPosting]')}
blogArticles.@process.sortBy = ${value.sort("datePublished", "DESC")}
blogArticles.@process.limit = ${value.slice(0, q(node).property('limit'))}
renderer = Neos.Demo:Presentation.Cards.Container {
content = Neos.Fusion:Loop {
items = ${props.blogArticles}
itemName = "blogPosting"
itemRenderer = Neos.Demo:Presentation.Cards.Card {
imageUri = Neos.Neos:ImageUri {
asset = ${q(blogPosting).property('image')}
maximumWidth = 400
maximumHeight = 225
}
title = ${q(blogPosting).property('title')}
content = ${q(blogPosting).property('abstract')}
uri = Neos.Neos:NodeUri {
node = ${blogPosting}
}
}
}
}
@cache {
mode = "cached"
entryIdentifier {
node = ${node}
}
entryTags {
# invalidate cache when the node rendered changes
1 = ${Neos.Caching.nodeTag(node)}
# invalidate cache when one of the selected blogs changes (might become hidden)
2 = ${Neos.Caching.nodeTag(q(node).property('blogs'))}
# invalidate cache when a descendent of the selected blogs changes
3 = ${Neos.Caching.descendantOfTag(q(node).property('blogs'))}
}
}
}
However, so far the list was empty. For any hint i’m super happy
Benjamin
(Benjamin A)
September 6, 2023, 12:31pm
2
I think i came a little bit more far here, but i’m still a bit clueless. I can see the correct pagination of the items of Blogposts (2). Also i’ve tried to minify the Short
NodeType:
##
# "ListableBlogList" element
#
prototype(Neos.Demo:Content.ListableBlogList) < prototype(Flowpack.Listable:PaginatedCollection) {
collection = ${q(site).find('[instanceof Neos.Demo:Document.BlogPosting]').get()}
itemsPerPage = 1
maximumNumberOfLinks = 2
listRenderer = 'Flowpack.Listable:Collection'
showPreviousNextLinks = true
}
prototype(Neos.Demo:Document.BlogPosting) < prototype(Neos.Demo:Document.Page) { ... }
/**
* "BlogPostingList" element for Flowpack.Listable
*/
prototype(Neos.Demo:Document.BlogPosting.Short) < prototype(Neos.Neos:ContentComponent) {
structuredData.blogPosting = Neos.Seo:StructuredData.RootObject {
type = "BlogPosting"
attributes = Neos.Fusion:DataStructure {
url = Neos.Neos:NodeUri {
node = ${documentNode}
}
author = Neos.Seo:StructuredData.Object {
type = "Person"
attributes.name = ${q(node).property('authorName')}
}
headline = ${q(node).property('title')}
abstract = ${q(node).property('abstract')}
datePublished = ${Date.format(q(node).property('datePublished'), 'Y-m-d')}
image = Neos.Seo:StructuredData.Object {
type = "ImageObject"
attributes.url = Neos.Neos:ImageUri {
asset = ${q(node).property('image')}
maximumWidth = 400
maximumHeight = 225
allowCropping = true
}
}
}
}
}
But now there is the following error thrown:
No Fusion object found in path "root<Neos.Fusion:Case>/documentType<Neos.Fusion:Matcher>/element<Neos.Demo:Document.Page>/content<Neos.Neos:ContentCollection>/content<Neos.Neos:ContentCollectionRenderer>/itemRenderer<Neos.Neos:ContentCase>/default<Neos.Fusion:Matcher>/element<Neos.Demo:Content.ListableNewsList>/renderer<Neos.Fusion:Array>/list<Neos.Fusion:Renderer>/element<Flowpack.Listable:Collection>/itemRenderer<Flowpack.Listable:ContentCaseShort>/default<Neos.Fusion:Matcher>/element<Neos.Demo:Document.BlogPosting.Short>/renderer" Please make sure to define one in your Fusion configuration.
root<Neos.Fusion:Case>/ documentType<Neos.Fusion:Matcher>/ element<Neos.Demo:Document.Page>/ content<Neos.Neos:ContentCollection>/ content<Neos.Neos:ContentCollectionRenderer>/ itemRenderer<Neos.Neos:ContentCase>/ default<Neos.Fusion:Matcher>/ element<Neos.Demo:Content.ListableNewsList>/ renderer<Neos.Fusion:Array>/ list<Neos.Fusion:Renderer>/ element<Flowpack.Listable:Collection>/ itemRenderer<Flowpack.Listable:ContentCaseShort>/ default<Neos.Fusion:Matcher>/ element<Neos.Demo:Document.BlogPosting.Short><Neos.Demo:Document.BlogPosting.Short>/
Anyway, the Fusion object Neos.Demo:Document.BlogPosting.Short
is existing
Benjamin
(Benjamin A)
September 6, 2023, 12:48pm
3
Okay i think it is because the original BlogPosting is inheriting from Type:
prototype(Neos.Demo:Document.Page)
while the Short
is inheriting from:
prototype(Neos.Neos:ContentComponent)
But when i inherit from Document.Page
, the whole page is rendered twice and everything is messed up
Benjamin
(Benjamin A)
September 13, 2023, 12:16pm
4
I found a solution, as it was somehow not possible to re-use the already exisiting properties and template, so i did it like that:
prototype(Neos.Demo:Document.BlogPosting.Short) < prototype(Neos.Neos:ContentComponent) {
date = ${Date.format(q(node).property('datePublished'), 'Y-m-d')}
authorName = ${q(node).property('authorName')}
title = ${q(node).property('title')}
content = ${q(node).property('abstract')}
uri = Neos.Neos:NodeUri {
node = ${node}
}
imageUri = Neos.Neos:ImageUri {
asset = ${q(node).property('image')}
width = 1248
height = 702
}
renderer = afx`
<div class="blogentry">
<div class="head">
<div class="tag">
{I18n.translate('Neos.Demo:Presentation.Cards:cards.authorPublishedBy')} {props.authorName}
</div>
<picture>
<img @if.has={props.imageUri} src={props.imageUri} aria-label={props.headline} alt={props.headline}/>
</picture>
<div>{I18n.translate('Neos.Demo:Presentation.Cards:cards.imageNotAvailable')}</div>
</div>
<div class="detail">
<h2>{props.title}</h2>
<div>
<p>
<!--
<time datetime={Date.format(props.date, 'Y-m-d')} @if={props.date}>
{Date.formatCldr(props.date, 'd. MMMM y')}
</time>
-->
<time>{props.date}</time>
</p>
<p>{props.content}</p>
</div>
<div class="more">
<a href={props.uri}">{I18n.translate('Neos.Demo:Presentation.Cards:cards.moreButton')}</a>
</div>
</div>
</div>
`
}
What i’ve noticed, somehow i can’t use the following as from the Neos.Demo example:
<time datetime={Date.format(props.date, 'Y-m-d')} @if={props.date}>
{Date.formatCldr(props.date, 'd. MMMM y')}
</time>
As it throws:
The given date "2023-04-27" was neither an integer, "now" or a \DateTimeInterface instance.
root<Neos.Fusion:Case>/ documentType<Neos.Fusion:Matcher>/ element<Neos.Demo:Document.Page>/ content<Neos.Neos:ContentCollection>/ content<Neos.Neos:ContentCollectionRenderer>/ itemRenderer<Neos.Neos:ContentCase>/ default<Neos.Fusion:Matcher>/ element<Neos.Demo:Content.ListableBlogList>/ renderer<Neos.Fusion:Array>/ list<Neos.Fusion:Renderer>/ element<Flowpack.Listable:Collection>/ itemRenderer<Flowpack.Listable:ContentCaseShort>/ default<Neos.Fusion:Matcher>/ element<Neos.Demo:Document.BlogPosting.Short>/ renderer<Neos.Fusion:Tag>/ content<Neos.Fusion:Tag>/ content<Neos.Fusion:Join>/ item_2<Neos.Fusion:Tag>/ content<Neos.Fusion:Join>/ item_2<Neos.Fusion:Tag>/ content<Neos.Fusion:Join>/ item_1<Neos.Fusion:Tag>/ content<Neos.Fusion:Join>/ item_1<Neos.Fusion:Tag>/ content<>/
By using {props.date}
it is working and i could also transform it e.g. with:
date = ${Date.format(q(node).property('datePublished'), 'd.m.Y')}
but why can’t i use Date.formatCldr
in that case?
What do you think about my solution? Also it would be great to find out why i can’t use the formatCldr function.
Thanks!
Benjamin
(Benjamin A)
September 15, 2023, 7:03am
5
Fixed, i didn’t had to format it twice…
changed from:
date = ${Date.format(q(node).property('datePublished'), 'Y-m-d')}
to just:
date = ${q(node).property('datePublished')}