[SOLVED] Need help with my blog package

Hey guys!
I created a blog package which has a BlogPostList-Plugin for listing blog posts on a page.
Now i have problems with rendering the single blog posts.

I have the correct blog posts in the blogPost variable and then i want to render them as a Collection. In the template i render the Collection path to display every single blog post. But that doesn’t work. Can someone help me and tell me my mistakes.

My fusion code:

prototype(DigitalpunktCom.Neos.Blog:BlogPostList) < prototype(TYPO3.Neos:Content) {
    templatePath = 'resource://DigitalpunktCom.Neos.Blog/Private/Templates/NodeTypes/BlogPostList.html'
    sectionName = 'BlogPostList'

    node = ${node}

    @context.blogFolderNode = ${q(node).property('blogFolderNode')}
    blogFolderNode = ${blogFolderNode}

    @context.allCategories = ${q(node).property('categories') ? q(node).property('categories') : NULL}
    @context.allTags = ${q(node).property('tags') ? q(node).property('tags') : NULL}
    blogLimit = ${q(node).property('blogLimit')}
    blogPosts = ${q(blogFolderNode).is('[instanceof DigitalpunktCom.Neos.Blog:BlogFolder]') ? q(blogFolderNode).find('[instanceof DigitalpunktCom.Neos.Blog:BlogPostsFolder]').children('[instanceof DigitalpunktCom.Neos.Blog:BlogPost]') : NULL}
    blogPosts.@process.filterBlogPostsByCategories = ${ value.filterBlogPostsByCategories(allCategories) }
    blogPosts.@process.filterBlogPostsByTags = ${ value.filterBlogPostsByTags(allTags) }

    @context.blogPosts = ${this.blogPosts}

    blogPostItemRenderer = TYPO3.TypoScript:Collection {
        collection = ${blogPosts}
        itemRenderer = DigitalpunktCom.Neos.Bootstrap:BlogPostListItem
        itemName = 'blogPost'
    }

    @cache {
        mode = 'uncached'
        context {
            1 = 'node'
            2 = 'documentNode'
            3 = 'site'
        }
    }
}

prototype(DigitalpunktCom.Neos.Bootstrap:BlogPostListItem) < prototype(TYPO3.TypoScript:Template) {
    templatePath = 'resource://DigitalpunktCom.Neos.Blog/Private/Templates/NodeTypes/BlogPostList.html'
    sectionName = 'BlogPostListItem'

    blogPost = ${blogPost}
}

My template:

{namespace blog=DigitalpunktCom\Neos\Blog\ViewHelpers}
{namespace neos=TYPO3\Neos\ViewHelpers}
{namespace typo3cr=TYPO3\TYPO3CR\ViewHelpers}
{namespace ts=TYPO3\TypoScript\ViewHelpers}

<f:section name="BlogPostList">
    <div class="blog-post-list">
        <f:if condition="{blogPosts}">
            <f:then>
                <ul class="posts">
                    <ts:render path="blogPostItemRenderer"/>
                </ul>
            </f:then>
            <f:else>
                <p>Error no blog posts!</p>
            </f:else>
        </f:if>
    </div>
</f:section>

<f:section name="BlogPostListItem">
    <li class="post">
        <div class="blog-title">
            <h2>
                <neos:link.node node="{blogPost}">{blogPost.properties.title}</neos:link.node>
                <f:if condition="{blogPost.removed}"> (removed)</f:if>
            </h2>
        </div>
        <p class="content">
            <blog:teaser node="{blogPost}"/>
            <neos:link.node node="{blogPost}" class="read-more">read more</neos:link.node>
        </p>
    </li>
</f:section>

I think it has something to do with collection = ${blogPosts} which is empty. But if i do a for each in the main template i get the correct number of “test” strings

<f:for each="{blogPosts}" as="blogPost">
        <h1> test</h1>
</f:for>

I think you could try TYPO3.Neos:ContentCase, i did the same with a carousel element:

prototype(My.Package:Carousel) < prototype(TYPO3.Neos:Content) {
templatePath = ‘resource://My.Package/Private/Templates/NodeTypes/Carousel.html’
carouselContent = TYPO3.TypoScript:Collection {
collection = ${q(node).children(’[instanceof TYPO3.Neos:ContentCollection]’).children()}
maximumLevels = 1
itemRenderer = My.Package:CarouselItem
itemName = ‘carouselItem’
}
carouselItemArray = ${q(node).children(‘carouselItems’).children()}
}
prototype(My.Package:CarouselItem) < prototype(TYPO3.Neos:Content) {
templatePath = 'resource://My.Package/Private/Templates/NodeTypes/CarouselItem.html’
itemContent = TYPO3.TypoScript:Collection {
collection = ${q(carouselItem)}
itemName = 'node’
itemRenderer = TYPO3.Neos:ContentCase
}
}

My problem is that i don’t get any blog posts at with collection = ${blogPosts}

Try to replace q(blogFolderNode) by q(this.blogFolderNode) and you don’t need to push blogFolderNode in the context

    blogFolderNode = ${q(node).property('blogFolderNode')}
    ...
    blogPosts = ${q(this.blogFolderNode).is('[instanceof DigitalpunktCom.Neos.Blog:BlogFolder]') ? q(this.blogFolderNode).find('[instanceof DigitalpunktCom.Neos.Blog:BlogPostsFolder]').children('[instanceof DigitalpunktCom.Neos.Blog:BlogPost]') : NULL}

I solved it with the help of the Shel.Blog Package

But i don’t really understand why my solution wasn’t working.

@dfeyer i already tried it that way, but the result was the same

Here my working code:

prototype(DigitalpunktCom.Neos.Blog:BlogPostList) < prototype(DigitalpunktCom.Neos.Bootstrap:Content) {
    templatePath = 'resource://DigitalpunktCom.Neos.Blog/Private/Templates/NodeTypes/BlogPostList.html'
    sectionName = 'BlogPostList'

    node = ${node}

    @context.blogFolderNode = ${q(node).property('blogFolderNode')}
    blogFolderNode = ${blogFolderNode}

    @context.allCategories = ${q(node).property('categories') ? q(node).property('categories') : NULL}
    @context.allTags = ${q(node).property('tags') ? q(node).property('tags') : NULL}
    blogLimit = ${q(node).property('blogLimit')}
    blogPosts = ${q(blogFolderNode).is('[instanceof DigitalpunktCom.Neos.Blog:BlogFolder]') ? q(blogFolderNode).find('[instanceof DigitalpunktCom.Neos.Blog:BlogPostsFolder]').children('[instanceof DigitalpunktCom.Neos.Blog:BlogPost]') : NULL}
    blogPosts.@process.filterBlogPostsByCategories = ${ value.filterBlogPostsByCategories(allCategories) }
    blogPosts.@process.filterBlogPostsByTags = ${ value.filterBlogPostsByTags(allTags) }
    #blogPosts.@process.sort = ${ value.sort('publicationDate','DESC') }
    #blogPosts.@process.slice = ${ Array.slice(value, 0, this.blogLimit) }

    @context.blogPosts = ${this.blogPosts}

    blogPostItemRenderer = TYPO3.TypoScript:Collection {
        collection = ${blogPosts}
        itemRenderer = DigitalpunktCom.Neos.Bootstrap:BlogPostListItem
        itemName = 'node'
    }

    @cache {
        mode = 'uncached'
        context {
            1 = 'node'
            2 = 'documentNode'
            3 = 'site'
        }
    }
}

prototype(DigitalpunktCom.Neos.Bootstrap:BlogPostListItem) < prototype(DigitalpunktCom.Neos.Bootstrap:Content) {
    templatePath = 'resource://DigitalpunktCom.Neos.Blog/Private/Templates/NodeTypes/BlogPostList.html'
    sectionName = 'BlogPostListItem'

    image = ${q(node).property('image')}
    description = ${q(node).property('description')}

    createDate = ${q(node).property('_creationDateTime')}

    prototype(DigitalpunktCom.Neos.Bootstrap:Image) {
        maximumWidth = 500
        maximumHeight = 500
    }

}

The template:

{namespace blog=DigitalpunktCom\Neos\Blog\ViewHelpers}
{namespace neos=TYPO3\Neos\ViewHelpers}
{namespace typo3cr=TYPO3\TYPO3CR\ViewHelpers}
{namespace ts=TYPO3\TypoScript\ViewHelpers}
{namespace media=TYPO3\Media\ViewHelpers}

<f:section name="BlogPostList">
    <div class="blog-post-list">
        <f:if condition="{blogPosts}">
            <f:then>
                <div class="row posts">
                    <f:for each="{blogPosts}" as="blogPost">
                        <ts:render path="blogPostItemRenderer.itemRenderer" context="{node: blogPost}"/>
                    </f:for>
                </div>
            </f:then>
            <f:else>
                <p>Error no blog posts!</p>
            </f:else>
        </f:if>
    </div>
</f:section>

<f:section name="BlogPostListItem">
    <div class="col-sm-4 post">
        <div class="blog-create-date">
            <f:translate id="blogPostList.createdOn" package="DigitalpunktCom.Neos.Blog" source="Main">Created on</f:translate>
            {createDate -> f:format.date(format:'D j. M Y')}
        </div>
        <f:if condition="{image}">
            <div class="blog-image">
                <figure class="image-alignment-center full-width">
                    <media:image asset="{image}" alt="{imageAlternativeText}" title="{imageTitle}" width="{width}"
                                 maximumWidth="{maximumWidth}" height="{height}" maximumHeight="{maximumHeight}"
                                 allowUpScaling="{allowUpScaling}" allowCropping="{allowCropping}" />
                </figure>
            </div>
        </f:if>
        <div class="blog-title headline underscored-left">
            <h2>
                <neos:link.node node="{node}">{node.properties.title}</neos:link.node>
                <f:if condition="{node.removed}"> (removed)</f:if>
            </h2>
        </div>
        <div class="blog-content">
            <p>{description}</p>
        </div>
        <div class="blog-more">
            <neos:link.node node="{node}" class="read-more"><f:translate id="blogPostList.readMore" package="DigitalpunktCom.Neos.Blog" source="Main">read more</f:translate></neos:link.node>
        </div>
    </div>
</f:section>

The first thing i see is that this is a strange use of blogPostItemRenderer

I would use it more like this,

in fluid

<f:if condition="{blogPosts}">
    <f:then>
        <ul class="posts">
        <f:for each="{blogPosts}" as="blogPost">
            <ts:render path="blogPostItemRenderer" context="{blogPost:blogPost}" />
        <f:for>
        </ul>
    </f:then>
    <f:else>
    <p>Error no blog posts!</p>
    </f:else>
</f:if>

in fusion/ts2

blogPostItemRenderer = DigitalpunktCom.Neos.Bootstrap:BlogPostListItem

For debugging you can try this before using the template again

prototype(DigitalpunktCom.Neos.Bootstrap:BlogPostListItem) < prototype(TYPO3.TypoScript:Value) {
    value = TYPO3.TypoScript:Debug {
         blogPost = ${blogPost}
    }
}

Thank you guys for your help!

I reworked my package. Now the solution looks like that (i removed some code, so that the post is not that long):

prototype(DigitalpunktCom.Neos.Blog:BlogPostList) < prototype(TYPO3.Neos:Content) {
`   templatePath = 'resource://DigitalpunktCom.Neos.Blog/Private/Templates/NodeTypes/BlogPostList.html'
    sectionName = 'BlogPostList'
    @context.blogPosts = ${this.blogPosts}

    blogPostRenderer = TYPO3.TypoScript:Collection {
        collection = ${blogPosts}
        itemRenderer = DigitalpunktCom.Neos.Blog:BlogPostRenderer
        itemName = 'node'
    }`
}

prototype(DigitalpunktCom.Neos.Blog:BlogPostRenderer) < prototype(TYPO3.TypoScript:Template) {
    templatePath = 'resource://DigitalpunktCom.Neos.Blog/Private/Templates/NodeTypes/BlogPostRenderer.html'
    sectionName = 'BlogPost'

    title = ${q(node).property('title')}
}

And the template for the BlogPostList nodeType

<f:section name="BlogPostList">
    <div class="blog-post-list">
        <ts:render path="blogPostRenderer"/>
    </div>
</f:section>

And the template for the BlogPostRenderer prototype

<f:section name="BlogPost">
    <div class="blog-post">
        <div class="blog-post-title">
            <h2>
                {title}
            </h2>
        </div>
    </div>
</f:section>