Jump to content

Load More button


Ana
 Share

Recommended Posts

Hello Ana,

As far as I know, there is no built-on system for that.
I would go for a url hook in the init.php file and a little script on the page that display your pages to retrieve more pages.

Find a way to store somewhere in your pages the number of already displayed pages (like a data-pages-number in your HTML wrapper).
Then add an event listener to your button that run a fetch on your url hook, sending the number of already displayed pages.

Inside your hook, get your pages, eliminate the pages already displayed and convert the pages data you want in JSON (like a title, a thumbnail, a link...).
Send this data as a response to the fetch.
Then, maybe with the help of a <template> tag, display these data on your page.

That would be my choice.

Link to comment
Share on other sites

@Ana To add that type of user-facing functionality would best be achieved using AJAX. I think that this is a perfect use case for htmx which works very well with ProcessWire and is probably the fastest and easiest method to get the type of behavior you're looking for.

Here's a working example of what this would look like. It takes about 5 minutes and you don't even have to leave your template file.

<!DOCTYPE html>
<html lang="en">
<head>
  <title><?=$page->title?></title>
</head>
  <body>
    <!-- ...the rest of your template markup -->

    <!-- Your button to load more pages -->
    <div>
      <button hx-get="<?=$page->url?>?content=remaining-pages" hx-target="#remaining-pages-container" hx-select="#remaining-pages">
        View More
      </button>
      <div id="remaining-pages-container">
        <!-- Your additional page markup will be loaded here -->
      </div>
    </div>

    <!-- This page list will only render if the URL has ?content=remaining-pages appended -->
    <?php if ($input->get->content === 'remaining-pages'): ?>
      <ul id="remaining-pages">
        <li>Remaining Pages</li>
        <?php foreach ($pages->find('your=selector,goes=here') as $remainingPage): ?>
          <li>
            <h2><?=$remainingPage->title?></h2>
            <a href="<?=$remainingPage->url?>">View Page</a>
          </li>
        <?php endforeach ?>
      </ul>
    <?php endif ?>
    <script src="https://unpkg.com/htmx.org@2.0.4" integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+" crossorigin="anonymous"></script>
  </body>
</html>

Explanation.

Having added the htmx script tag to your document, the htmx library is available. Here's what happens:

  • Clicking the "View More" button makes an AJAX request to the server
  • The URL for the hx-get attribute has been appended with "?content=remaining-pages", this can be anything you prefer
  • The conditional block for additional pages will only render if the ProcessWire $input->get->content matches the GET variable we appended to the hx-get attribute URL
  • When the page is rendered and response sent back for the AJAX request, htmx finds the element with the id 'remaining-pages'
  • If an element with the id of 'remaining-pages' is found, then the contents of that element are inserted into an element with the id of  'remaining-pages-container' which is specified in the hx-target attribute of the <button> element

There are some other ways that you could organize your code and return the markup, that's entirely up to you and how you would like to organize that in your ProcessWire site.

This works, but we can make this more efficient. In the example above, the entire page is rendered just to get the remaining pages. This may not be an issue for all websites, but if a page has a lot of fields or other features that make database calls, then there is a lot of work being done on the server to render content that won't be shown because htmx is only selecting the content inside the element with the id of 'remaining-pages'. Here's an improvement:

<!-- This page list will only render if the URL has ?content=remaining-pages appended -->
<?php if ($input->get->content === 'remaining-pages'): ?>
  <ul id="remaining-pages">
    <li>Remaining Pages</li>
    <?php foreach ($pages->find('your=selector,goes=here') as $remainingPage): ?>
      <li>
        <h2><?=$remainingPage->title?></h2>
        <a href="<?=$remainingPage->url?>">View Page</a>
      </li>
    <?php endforeach ?>
  </ul>
  <?php return; ?>
<?php endif ?>
<!DOCTYPE html>
<html lang="en">
<head>
  <title><?=$page->title?></title>
</head>
  <body>
    <!-- ...the rest of your template markup -->

    <!-- Your button to load more pages -->
    <div>
      <button hx-get="<?=$page->url?>?content=remaining-pages" hx-target="#remaining-pages-container" hx-select="#remaining-pages">
        View More
      </button>
      <div id="remaining-pages-container">
        <!-- Your additional page markup will be loaded here -->
      </div>
    </div>
    <script src="https://unpkg.com/htmx.org@2.0.4" integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+" crossorigin="anonymous"></script>
  </body>
</html>

This is the exact same code as above, but here's what we did differently this time.

  • The markup for the additional pages that only renders if 'content=additional-pages' is present has been moved above all of the other markup in the template
  • After the closing <ul> tag and within the <?php endif ?> statement, we've added a return statement that prevents ProcessWire from rendering the rest of the page

Depending on how "heavy" your template is, this could make the results appear to the user faster and very little work was needed on our part to do that.

There are things that you can explore to make use of other ProcessWire features and improve the readability and/or reusability of your code

  • Rather than using a GET variable, you could choose to use URL segments in ProcessWire to create and respond to a more natural URL
  • You could use the render feature of FileTools in ProcessWire to store your remaining pages markup in a separate file
  • You could use a GET variable such as "count=6" to set the number of pages to return rather than hard coding it

Those are entirely optional, the example above is all you need to implement the feature you are looking for.

Some notes on htmx

  • If you use a build tool and npm, you can add htmx to your project as a package rather than the <script> tag
  • htmx offers an easy way to create a 'loading' animation to let your users know that the button is retrieving the remaining pages while the AJAX request is being processed

Hope this is useful for your project! The code example really did take only 5 minutes (maybe less!), without one line of JavaScript.

If you prefer using a JavaScript oriented approach with JSON and markup such as the <template> tag as @TomPich mentioned, the same thing could be achieved using Alpine.js which is an easy way to add enhancements to your templates without the need for a full front end framework (just another personal favorite).

  • Like 3
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...