The javascript component, which handles the loadMore could look like this:
// components/AjaxLink.js
import * as $ from 'jquery';
export default class AjaxLink {
$el;
$container;
loading = false;
enableLoader;
loadingClass;
initialize = (el, options) => {
this.$el = $(el);
this.$container = options.container || $(`#${el.id}-container`);
this.enableLoader = !!options.loadingClass || !!options.enableLoading;
this.loadingClass = options.loadingClass || `${this.getFirstClass(this.$el)}--loading`;
this.bindEvents();
};
getFirstClass = ($item) => {
return $item[0].classList[0];
};
bindEvents = () => {
this.$el.on('click', this.handleClick);
};
get url() {
const url = new URL(this.$el.attr('href'), window.location.href);
url.searchParams.set('partial', 'true');
return url.href;
}
appendItems = (items) => {
this.$container.append(items);
};
changeHref = (href) => {
this.$el.attr('href', href);
};
removeLoadMoreLink = () => {
this.$el.remove();
};
toggleLoadingClass = () => {
this.$el.toggleClass(this.loadingClass);
};
handleClick = (e) => {
e.preventDefault();
if (this.loading) {
return;
}
this.loading = true;
if (this.enableLoader) {
this.toggleLoadingClass();
}
$.ajax(this.url, {
error: () => {
this.removeLoadMoreLink();
},
success: (data) => {
data = $(data);
const items = data.find(`#${this.$container.attr('id')}`).html();
const loadMoreLink = data.find(`#${this.$el.attr('id')}`);
this.appendItems(items);
if (loadMoreLink.length) {
this.changeHref(loadMoreLink.attr('href'));
} else {
this.removeLoadMoreLink();
}
},
complete: () => {
if (this.enableLoader) {
this.toggleLoadingClass();
}
this.loading = false;
},
});
};
}
Register it using:
// main.js
import * as web from '@sulu/web';
import AjaxLink from './components/AjaxLink';
web.registerComponent('ajax-link', AjaxLink);
window.web = web;
In the twig you can implement it as following:
{% if content.items|length %}
<div class="container">
{% set ajaxLinkId = register_component('ajax-link', { enableLoading: true }) %}
<div class="grid" id="{{ ajaxLinkId }}-container">
{% for item in content.items %}
...
{% endfor %}
</div>
{% if view.items.paginated and view.items.hasNextPage|default %}
<div>
{% set queryParams = app.request.query.all|merge({
'page': view.items.page + 1,
}) %}
<a class="load-more" id="{{ ajaxLinkId }}" href="?{{ queryParams|url_encode }}" rel="next">
Load more
</a>
</div>
{% endif %}
</div>
{% endif %}
Your smart content should like this:
<property name="items" type="smart_content">
<meta>
<title lang="en">Items</title>
</meta>
<params>
<param name="provider" value="pages"/>
<param name="max_per_page" value="12"/>
<param name="page_parameter" value="page"/>
<param name="properties" type="collection">
<param name="title" value="title"/>
</param>
</params>
</property>