How to show pieces into the another pieces?

2019-07-15 04:51发布

问题:

I have two type of pieces one is Authors and second one is Articles. I can show the list of articles (by using indexAjax.html and index.html in articles-pages) as it is implemented in Apostrophe's Demo and the list of Authors as well (by using indexAjax.html and index.html in authors-pages/views).

My question is how can I show the articles written by some specified author in by using show.html file of authors-pages/views ?
So when user clicks on some author he/she should be able to see the list of articles written by the specified author.

The lib/modules/articles/index.js file is the following

module.exports = {
    extend: 'apostrophe-pieces',
    name: 'articles',
    label: 'Article',
    pluralLabel: 'Articles',
    contextual: true,
    addFields: [
        {
            name: '_author',
            type: 'joinByOne',
            withType: 'author',
            label: 'Author',
            idField: 'author',
            filters: {
                projection: {
                    title: 1,
                    slug: 1,
                    type: 1,
                    tags: 1
                }
            }
        },

....

    ]

};

Any help will be appreciated!

回答1:

I'm the architect of Apostrophe at P'unk Avenue.

The code in your own solution effectively reimplements a feature we already have: reverse joins.

You already have a "forward" join (joinByOne). So use joinByOneReverse to make those items available from the "other side."

In the schema for authors, you can write this:

addFields: [
  {
    name: '_articles',
    type: 'joinByOneReverse',
    withType: 'articles',
    label: 'Articles',
    idField: 'author',
    filters: {
      projection: {
        title: 1,
        slug: 1,
        type: 1,
        tags: 1
      }
    }
  }
]

This makes a ._articles array property available on each author.

It is important to note that idField doesn't change. We are intentionally using the same information so that we get the same content.

If you wish, you can also set ifOnlyOne: true on that field to avoid having it fetched for the index page and other contexts where you load more than one author.

Check out the guide to schemas for more information.



回答2:

I found an answer for my own question (before seeing the posted alternative answer). Hope it will be useful for others.

So there are two pieces articles and authors.

lib/modules/authors-pages/index.js

module.exports = {
    extend: 'apostrophe-pieces-pages',
    articlesPerPage: 3,
    construct: function (self, options) {
        var beforeShow = self.beforeShow;
        self.beforeShow = function (req, callback) {
            var limit = self.options.articlesPerPage;
            var skip = req.query.page || 1;
            skip = (parseInt(skip) - 1) * limit;
            if (!req.data || !req.data.piece) {
                return beforeShow(req, callback);
            }
            var cursor = self.apos.docs.getManager('articles').find(req, {
                author: req.data.piece._id
            });
            cursor
                .skip(skip)
                .limit(limit)
                .sort({ createdAt: -1 })
                .toArray(function (err, articles) {
                    req.data._articles = articles || [];
                    req.data.currentPage = Math.ceil((skip + 1) / limit);
                    cursor.toCount(function(err, count){
                        if(err)
                            count = 1;
                        req.data.totalPages = Math.ceil(count / limit);
                        beforeShow(req, callback);
                    })

                })
        }
    }
}

lib/modules/authors-pages/view/show.html

{% extends data.outerLayout %} 
{% block title %}
    {{ data.piece.title }}
{% endblock %} 
{% block main %}
    {% for article in data._articles %}
        <p>{{article.title}}</p>    
    {% endfor %}
    {% import 'apostrophe-pager:macros.html' as pager with context %}
    {{ pager.render({ page: data.currentPage, total: data.totalPages }, data.url) }}
{% endblock %}