2

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!

Karlen
  • 1,294
  • 13
  • 20
  • Hi Karlen, use the joinByArray [guide](http://apostrophecms.org/docs/tutorials/getting-started/schema-guide.html#code-join-by-array-code) as a starting point. – robert-jakobson Mar 09 '17 at 14:50
  • Hi @robert-jakobson, thanks for your comment. I have already find a solution. I didn't want to use `joingByArray` because once any article created the id of article should be added into that list, hence it will bring one to one linking between db docs which I think is not good idea for this particular case. – Karlen Mar 09 '17 at 20:33

2 Answers2

3

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.

Tom Boutell
  • 7,281
  • 1
  • 26
  • 23
  • 1
    Thank you. I've checked almost the all pages of documentation, but didn't realized this option or forgot that, or maybe I have overlooked the docs. Anyway thanks for the great platform and for your answer as well! – Karlen Mar 10 '17 at 13:22
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 %}
Karlen
  • 1,294
  • 13
  • 20