adonis.jsのページネーションリンクを作成する



Node.js製のMVCフレームワーク「adonis.js」のページネーションリンク作成方法の紹介です。

以前に "Laravelライクなnode.jsのフレームワーク「adonis.js」"として紹介したことがあるadonisですが、現在はバージョンも3.*系になり、使い勝手も良くなりました。

adonisのデータベースを操作する"Query Builder"にはページネーション機能が備わっていますが、View側でページネーションのリンクを作成する機能は用意されていません。

{{-- Laravelではこのように簡単にページネーションのリンクが作成できます --}}
{{ $page->links() ]}

っということで、LaravelのようにView側で簡単にページネーションリンクが生成できるようにテンプレートマクロを作ってみました。
( adonis framework 3.0.1を使って動作検証、Twitter Bootstrap用に作りました )

* このようなページネーションリンクを作成してみました


ページネーション用のクエリを作成

adonisのQuery-Builderでpagination関数を使うと下記のようなデータが返ってきます。

const Database = use('Database')
// query
const articles =
      yield Database
      .from('articles')
      .paginate(1, 10);

// paginate(ページ, ページのアイテム数)

// return
{
  total: 177,
  currentPage: 1,
  perPage: 10,
  lastPage: 18,
  data: [...]
}


クエリ自体は問題ないですが、上記のままだとのリンクボタンを押してもページを割当られないのでurlのパラメーターをページネーションに渡す必要があります。

そこで、URLのクエリストリングを取得してページネーションにページを渡す関数を作りました。

query_string(request) {
   // get url query string *exp, ?page=[num]
   // もしqueryストリングを'page'以外にしたい場合は下記を変更すれば可能です
   const page = request.get().page;

   try {

    if (typeof page == 'undefined') {
        throw ('query of "page" is undefined');
       }

    if (page == 0 || page == 1) {
        throw ('return page 1');
       }

        return page;

      } catch (e) {
        return 1;
    }

} // !End query_string()
// controllerでの処理
* pagination(request, response) {
   // paginationの第一引数でquery_string関数を使っています
   const articles =
     yield Database
     .from('articles')
     .paginate(query_string(request), 10);
      
   // resources/views/pagination
   yield response.sendView('pagination', {
        article: articles
   });
    
}


ページネーションリンク用のmacroを作成 

adonisはテンプレートエンジンにnunjucksが使われています。

nunjucksはjavascript用のテンプレートエンジンで"jinja2"というPython用のテンプレートエンジンに影響を受けて作られており、PHPの"Twig"、Pythonの"Django"のテンプレートに使い勝手 & 機能が似ています。
( 過去記事: Mozilla製のjavascriptテンプレートエンジン「Nunjucks」 )

nunjucksにはmacroというViewをテンプレート化して使いまわせる機能が用意されているので、macro使ってページネーション リンク用のViewを作ります。
( jinja2には勿論のこと、twigにもmacro機能は用意されています )

{#  resource/views/macros/pagination.njk #}
{#
  query: database query
  q_str: query string (default= page)
#}
{% macro pagination(query, q_str='page') %}
  
  {# show pagination if page is greater than 1  #}
  {% if query.lastPage > 1 %}

    <ul class="pagination">
      
      <!-- previous page link -->
      {% if query.currentPage == 1 %}
        <li class="disabled">
          <span>
            <i class="glyphicon glyphicon-chevron-left"></i>
          </span>
        </li>
      {% else %}
      
        {# Go To First Page  #}
        {% if query.currentPage != 1 %}
          <li>
            <a href="?{{q_str}}=1" rel="next">
              <i class="glyphicon glyphicon-backward"></i>
            </a>
          </li>
        {% endif %}
        
        <li>
          <a href="?{{q_str}}={{ (query.currentPage - 1) }}" rel="prev">
            <i class="glyphicon glyphicon-chevron-left"></i>
          </a>
        </li>

      {% endif %}
      
      
      <!-- conent links -->
      {% for item in
        range((query.currentPage - 2 | abs), query.currentPage + 5)
        %}
        
        {# to be disabled when duplicate page to content  #}
        {% if item == query.currentPage %}
          <li class="disabled"><span>{{ item }}</span></li>
        
        {% else %}
        
          {% if item > 0 and item <= query.lastPage %}
            <li><a href="?{{q_str}}={{ item }}"> {{ item }}</a></li>
          {% endif %}
          
        {% endif %}
        
      {% endfor %}
      
      
      <!-- Next Page Link -->
      {% if query.lastPage == query.currentPage
            or
            query.lastPage <= query.currentPage %}
            
        <li class="disabled">
          <span>
            <i class="glyphicon glyphicon-chevron-right"></i>
          </span>
        </li>
        
      {% else %}
        <li>
          <a href="?{{q_str}}={{ (query.currentPage + 1) }}" rel="next">
            <i class="glyphicon glyphicon-chevron-right"></i>
          </a>
        </li>
        
        {# last page link  #}
        {% if query.currentPage != query.lastPage %}
        <li>
          <a href="?{{q_str}}={{ query.lastPage }}" rel="next">
            <i class="glyphicon glyphicon-forward"></i>
          </a>
        </li>
        {% endif %}
        
      {% endif %}
      
    </ul>
    {% endif %}
    
{% endmacro %}
  

( ファイルのパス: /resouces/views/macros/pagination.njk )


テンプレート上でページネーションリンクを使う 

上で作成したページネーション用のmacroを通常のテンプレート上で使っていきます。javascriptらしく from 'template' import 'func'という形でmacroの読み込みが可能です。
( bootstrap用に作っていますが、クラスを変えれば他のcssフレームワークにも流用できます )

<div class="container">
    <h3>Adonis pagination example with bootstrap 3 </h3>
    <h4>current page: {{ article.currentPage }},
          last page: {{ article.lastPage}}</h4>

    <ul>
        {# ariticle #} 
        {% for article in article.data %}
        <li>
            <a>{{ article.title }}</a>
        </li>
        {% endfor %}

    </ul>

    {# import macro for pagination #} 
    {% from "macros.pagination" import pagination %} 
  
    {# call pagination macro and to allocate variable #} 
    {{ pagination(article) }}

</div>

( ファイルパス: /resouces/views/pagination.njk )

Summary 

以上がadonisでページネーションリンク用のViewを作る説明でした。

Laravelと使い勝手を似せる為にbootstrap用に作りましたが、他のCSSフレームワーク用に作ることも比較的簡単にできます。

adonisは、Laravel 又は Lumenを使って開発したことがある人には取っ付き易いフレームワークなので、ゼヒ×2チェックしてみてください!

Adonis : Query-builder (pagination)

 

この記事のカテゴリ
プログラミング

この記事に付けられているタグ