Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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);
            }
        },
    });
});
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top