Kadir Oz
Kadir Oz

Reputation: 33

Masonry view not working after loading more posts via ajax

I'm using this method to load more posts with Ajax.

I'm also using Masonry for the posts layout.

Masonry works fine for the first set of posts, but not for the next set of posts that are appended after clicking load more posts.

How can I make Masonry work after loading more posts?

Screen before click

Images representing blog posts

Screen after click

Images representing blog posts positioned wrongly

Source Code:

index.php

<!-- Post Layout -->
<div class="posts <?php echo $home_style; ?>">

    <!-- Normal Post -->
    <?php

    if (have_posts()) :

        /* Start the Loop */
        while (have_posts()) : the_post();

            /* Home Layout */
            if ($home_style === 'standard') {
                get_template_part('inc/posts/content');
            } else {
                get_template_part('inc/posts/content', 'grid');
            }

        endwhile;

    else :

        get_template_part('template-parts/content', 'none');

    endif;

    ?>

    <?php
    global $wp_query; // you can remove this line if everything works for you

    // don't display the button if there are not enough posts
    if ($wp_query->max_num_pages > 1)
        // you can use <a> as well
        echo '<div class="misha_loadmore grid-post">More posts</div>';
    ?>


</div>
<!-- Post Layout / END -->

Ajax Code

jQuery(function ($) {
  $('.misha_loadmore').click(function () {

    var button = $(this),
      data = {
        'action': 'loadmore',
        'query': misha_loadmore_params.posts, 
        'page': misha_loadmore_params.current_page
      };

    $.ajax({
      url: misha_loadmore_params.ajaxurl, // AJAX handler
      data: data,
      type: 'POST',
      beforeSend: function (xhr) {
        // change the button text, you can also add a preloader image
        button.text('Loading...'); 
      },
      success: function (data) {
        if (data) {
          button.text('More posts').prev().before(data); // insert new posts
          misha_loadmore_params.current_page++;

          if (misha_loadmore_params.current_page == misha_loadmore_params.max_page)
            button.remove(); // if last page, remove the button

          // you can also fire the "post-load" event here 
          // if you use a plugin that requires it
          // $( document.body ).trigger( 'post-load' );
        } else {
          button.remove(); // if no data, remove the button as well
        }
      }
    });
  });
});

Masonry script.js

/* Masonary Grid */
$('.home-grid').masonry({
  itemSelector: '.grid-post',
  percentPosition: true,
  gutter: 33
});

Upvotes: 3

Views: 2650

Answers (1)

Cave Johnson
Cave Johnson

Reputation: 6778

In most javascript libraries, if you change the DOM (HTML) after initializing the plugin, you will have to tell the library that changes have been made. Most libraries will include a function or listen to an event that tells it to update. In the case of Masonry, it looks like this function is reloadItems.

In your case, it looks like you will have to call $('.home-grid').masonry('reloadItems'); directly after you do button.text( 'More posts' ).prev().before(data);.

Full code:

jQuery(function ($) {
  $('.misha_loadmore').click(function () {

    var button = $(this),
      data = {
        'action': 'loadmore',
        'query': misha_loadmore_params.posts,
        'page': misha_loadmore_params.current_page
      };

    $.ajax({
      url: misha_loadmore_params.ajaxurl, // AJAX handler
      data: data,
      type: 'POST',
      beforeSend: function (xhr) {
        button.text('Loading...');
      },
      success: function (data) {
        if (data) {
          button.text('More posts').prev().before(data); // insert new posts
          $('.home-grid').masonry('reloadItems');
          misha_loadmore_params.current_page++;

          if (misha_loadmore_params.current_page == misha_loadmore_params.max_page)
            button.remove(); // if last page, remove the button

        } else {
          button.remove(); // if no data, remove the button as well
        }
      }
    });
  });
});

Upvotes: 3

Related Questions