0

I'm at a dead end. I'm trying realise custom pagination on frontend page.

So, hear my code in modulename/view/frontend/web/js/blog.js

define([
    'jquery',
    'ko',
    'uiComponent',
    'domReady!'
], function (
    $,
    ko,
    Component
) {
    'use strict';

    let page = 1;
    let limit = 0;
    let total = 0;
    let numPages = 1;

    let getQuery = (page) => {
        let tmp = {
            data: [],
            limit: 0,
            total: 0
        };
        $.ajax({
            async: false,
            global: false,
            url: "/blog/index/get?page=" + page,
            method: 'GET',
            success: function (res) {
                tmp.data = res.data;
                tmp.page = res.page;
                tmp.limit = res.limit;
                tmp.total = res.total;
                tmp.num_pages = res.num_pages;
            }
        });
        return tmp;
    };

    let changePage = (page) => {
        let btn_next = document.getElementById("btn_next");
        let btn_prev = document.getElementById("btn_prev");

        // Validate page
        if (page < 1) {
            page = 1
        }
        if (page > numPages) {
            page = numPages;
        }

        if (page === 1) {
            btn_prev.style.visibility = "hidden";
        } else {
            btn_prev.style.visibility = "visible";
        }

        if (page === numPages) {
            btn_next.style.visibility = "hidden";
        } else {
            btn_next.style.visibility = "visible";
        }
    };

    return Component.extend({
        defaults: {
            template: 'Magespace_Blog/blog'
        },
        initialize: function (config) {
            this._super();
            this.getPosts(config.page)
            console.log(ko);

            return this;
        },
        getDate: (value) => {
            const date = new Date(value);
            return date.getMonth() + ' ' + date.getDate() + ', ' + date.getFullYear();
        },

        getPosts(pageArg) {
            let res = getQuery(pageArg);
            page = res.page;
            total = res.total;
            limit = res.limit;
            numPages = res.num_pages;
            this.posts = res.data;
        },

        prevNextBtns: () => {
            let btn_prev = document.getElementById("btn_prev");
            let btn_next = document.getElementById("btn_next");

            if (page < 2) {
                btn_prev.style.visibility = 'hidden';
            }
            if (numPages === 1 || page === numPages || page > numPages) {
                btn_next.style.visibility = 'hidden';
            }
        },

        prevPage: () => {
            if (page > 1) {
                page--;
                changePage(page);
            }
        },

        nextPage: () => {
            if (page < numPages) {
                page++;
                changePage(page);
            }
        },
    });
});

modulename/view/frontend/templates/blog.phtml

<?php

/** @var Magento\Framework\View\Element\Template $block */
$page = $block->getRequest()->getParam('page') ?? 1;
$blogViewModel = $block->getData('viewModel');
?>

<div class="blog-container" data-bind="scope: 'blog'">
    <!-- ko template: getTemplate() --><!-- /ko -->
</div>

<script type="text/x-magento-init">
    {
        "*": {
                "Magento_Ui/js/core/app": {
                    "components": {
                        "blog": {
                            "component": "Magespace_Blog/js/blog",
                            "posts": [],
                            "total": <?= $blogViewModel->getTotalPostsCount() ?>,
                            "page": <?= $page ?>
                        }
                    }
                }
             }
    }
</script>

modulename/view/frontend/web/template/blog.html

<ul>
    <!-- ko foreach: { data: posts, as: 'post' } -->
    <li class="post-container" data-bind="attr: {id: post.id}">
        <div class="post-image"></div>
        <div class="post-container__content">
            <a data-bind="attr:{href: post.url}"><h2 data-bind="text: post.title"></h2></a>
            <div class="post-meta">
                <div class="column-1" data-bind="text: $parent.getDate(post.published_time)"></div>
                <div class="column-2" data-bind="text: post.author"></div>
            </div>
            <p data-bind="text: post.content"></p>
        </div>
    </li>
    <!-- /ko -->
</ul>
<div class="pagination" data-bind="afterRender: prevNextBtns()">
    <a id="btn_prev" data-bind="click:prevPage">Prev</a>
    <a href="#" class="active">1</a>
    <a id="btn_next" data-bind="click:nextPage">Next</a>
</div>

How i can update post list in tag (modulename/view/frontend/web/template/blog.html) from uiComponent, when an ajax request occurs?

0

You need to set this.posts as a KO observable and then update that. At the moment you are simply updating a JS object which will not inform KO to update the frontend.

Within Component.extend add:

posts: ko.observable(),

Rather than this.posts = res.data; use this.posts(res.data)

This will update this.posts with the new data, which will in turn update the frontend.

1
  • 1
    Thanks! I had to think a little. But the direction was given right. Apr 2 at 3:29
0

Thanks to Ben Crook. It's working!

That's what I got.

define([
    'jquery',
    'ko',
    'uiComponent',
    'domReady!'
], function (
    $,
    ko,
    Component
) {
    'use strict';

    / ... /

    return Component.extend({
        defaults: {
            template: 'Magespace_Blog/blog'
        },

        posts: ko.observable([]),

        initialize: function (config) {
            self = this;
            this._super();
            self.getPosts(config.page)
            return this;
        },

        initObservable: function () {
            this._super();
            this.observe('posts');

            return this;
        },

        / ... /

        getPosts(pageArg) {
            let res = getQuery(pageArg);
            page = res.page;
            total = res.total;
            limit = res.limit;
            numPages = res.num_pages;
            this.posts(res.data);
        },

        / ... /

        prevPage: () => {
            if (page > 1) {
                page--;
                changePage(page);
                self.getPosts(page);
            }
        },

        nextPage: () => {
            if (page < numPages) {
                page++;
                changePage(page);
                self.getPosts(page);
            }
        },
    });
});
2
  • you can also start refactoring your code by replacing all DOM logic (such as btn_next.style.visibility) by using knockout observable
    – Jimmy
    Apr 2 at 3:54
  • @Jimmy Thanks! I'll do that Apr 2 at 5:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.