Comment pagination without reloading the page
Proposed Functionality
You can post, edit, flag, delete comments without refreshing page. But you can't go to paginated pages without refreshing. How come you can post, but can't load next page with ajax or fetch. My propose is to use ajax/fetch to load paginated pages.
Use Case
Types >
- auto loadwith scroll with ajax/fetch > no click needed
- keep current pagination links, but load with ajax/fetch > onclick on link
Changes
Only small js code need to be changed. I can create a pull request if you want.
This is a very useful suggestion. We'll be looking forward to it. @ChathuraGH , please tell me, without PR, what changes do I need to make in order for the "Load more" button to appear? (I'm a beginner developer, I'll be grateful)
@ogurec-ogurec , What version do you use? django-comments-dab version. because answer changes with version.
For django-comments-dab==1.6.7
@ogurec-ogurec , @Radi85 .
I have spend some time for the task now. Maybe there are lot of variations in this design. As
- use ajax(jQuery)
- use fetch
- not query full page(medium code change)
- use iframe
- use auto load on scroll > no buttons, no clicks, infinity scroll
- use more button to load onclick
- use pagination buttons to replace content
- query full page(small code changes) . So anything is possible. It is just a matter of work that you have to put in to. Every combination has its own pros and cons. So for now, I have used option 2,8,6.
@ogurec-ogurec , @Radi85
Steps
1)
- Select one of your django apps
- go to template folder
- create folder 'comment'
- go in to this folder
- create folder 'comments'
- go in to this folder
- create 'pagination.html' file
- put the below code in this file
<nav id="pagination-nav" aria-label="Page navigation" class="mt-3 mb-5">
<ul class="pagination justify-content-center pagination-sm">
{% if comments.has_next %}
<li class="{{li_cls}}">
<a class="page-link {{text_style}}" onclick="event.preventDefault();Load_Commentsx(this);" href="?page={{ comments.next_page_number }}#comments" style="color:blue;font-weight:bold;font-size:large;" aria-label="Next">
Get More Comments
</a>
</li class="{{li_cls}}">
{% endif %}
</ul>
</nav>
2)
- Put below code inside(anywhere) your template(where you render your comments) > best if put at the bottom of page
<script type="text/javascript">
function Load_Commentsx(e){
var q_url=e.href;
let response = fetch(q_url).then(function(response) {
if (response.ok) {
response.text().then(function(text) {
document.querySelector('#pagination-nav').remove();
document.querySelector('#Modal').remove();
const template = document.createElement('template');
template.innerHTML = text;
var elem=document.querySelector('#comments div.js-main-comment');
const lightBoxContent1 = template.content.querySelector('#comments div.js-main-comment');
elem.innerHTML = elem.innerHTML + lightBoxContent1.innerHTML;
var elem2=document.querySelector('#comments');
const lightBoxContent2 = template.content.querySelector('#comments #Modal');
elem2.appendChild(lightBoxContent2);
const lightBoxContent3 = template.content.querySelector('#comments #pagination-nav');
elem2.appendChild(lightBoxContent3);
});
}
});
};
</script>
3)
Render your comments as usual.
Happy Coding.💓⭐⚡😀.
@ChathuraGH wow, big thanks, I struggled for almost a week to implement something like this. I ran off to test it, I'll come back with feedback.
I am excited to see your feedback 👀.
@ChathuraGH I tested it, added the code to the file site-packages\comment\templates\comment\comments\pagination.html, the button appeared, the button has the desired value of the next page in the link, but when clicked, nothing is loaded, and there is an error in the console:
Uncaught (in promise) TypeError: Cannot read properties of null (reading 'innerHTML')
here in this line:
apparently, there's something wrong with the selectors.
DAB version: v2.8.0 (last)
Somewhat expected behaviour, because I didn't know your version. I will post working code for your version.
@ogurec-ogurec , @Radi85 . I just tested for your(@ogurec-ogurec ) version(DAB version: v2.8.0 (last)). It works.
JS CODE
<script type="text/javascript">
function Load_Commentsx(e){
var q_url=e.href;
let response = fetch(q_url).then(function(response) {
if (response.ok) {
response.text().then(function(text) {
// remove > #pagination-nav + #Modal
document.querySelector('#pagination-nav').remove();
document.querySelector('#Modal').remove();
// template
var template = document.createElement('template');
template.innerHTML = text;
// add new comments
var old_comments=document.querySelector(''section#comments div.mt-5');
const new_comments_section= template.content.querySelector('section#comments div.mt-5');
old_comments.innerHTML = old_comments.innerHTML + new_comments_section.innerHTML;
///////
var elem2=document.querySelector('#comments');
//2 add new #Modal
var new_Modal = template.content.querySelector('#comments #Modal');
elem2.appendChild(new_Modal );
//3 add new #pagination-nav
var new_pagination_nav = template.content.querySelector('#comments #pagination-nav');
elem2.appendChild(new_pagination_nav );
});
}
});
};
</script>
TEMPLATE CODE
{% load i18n %}
<nav id="pagination-nav" aria-label={% trans "Page navigation" %} class="mt-3 mb-5">
{% trans "Get More Comments" as Get_More_Comments %}
<ul class="pagination justify-content-center pagination-sm">
{% if comments.has_next %}
<li class="{{li_cls}}">
<a class="page-link {{text_style}}" onclick="event.preventDefault();Load_Commentsx(this);" href="?page={{ comments.next_page_number }}#comments" style="color:blue;font-weight:bold;font-size:large;" aria-label={{ Get_More_Comments }}>
{{ Get_More_Comments }}
</a>
</li class="{{li_cls}}">
{% endif %}
</ul>
</nav>
Happy Coding.💓⭐⚡😀.
What happened bro? Did you succeed?
@ChathuraGH thanks the code, i add code to the pagination.html, but there is an error when starting:
here in this line:
<a class="page-link text-success" onclick="event.preventDefault();Load_Commentsx(this);" href="?page=2#comments" style="color:blue;font-weight:bold;font-size:large;" aria-label=Get More Comments>
Get More Comments
</a>
what could it be?
I know what it is. Where did you put JS CODE? This happens when js code is not present.
That's it, I found a mistake, there was one extra quote,
var old_comments=document.querySelector(''section#comments div.mt-5');
, now it works, but a new problem has appeared, after the comments are loaded from the second page, the button and pagination disappear, and the comments are no longer loaded. Roughly speaking, comments are loaded only from the second page, although there are many more comments
ok.... I see it now..
can you try removing spaces here..
elem2.appendChild(new_Modal );<<<<<
//3 add new #pagination-nav
var new_pagination_nav = template.content.querySelector('#comments #pagination-nav');
elem2.appendChild(new_pagination_nav );<<<<
The below code works for me, bro..
// with support to DAB version: v2.8.0 (last)(2023/12)
function Load_Commentsx(e){
var q_url=e.href;
let response = fetch(q_url).then(function(response) {
if (response.ok) {
response.text().then(function(text) {
// remove > #pagination-nav + #Modal
document.querySelector('#pagination-nav').remove();
document.querySelector('#Modal').remove();
// template
var template = document.createElement('template');
template.innerHTML = text;
// add new comments
var old_comments=document.querySelector('section#comments div.mt-5');
const new_comments_section= template.content.querySelector('section#comments div.mt-5');
old_comments.innerHTML = old_comments.innerHTML + new_comments_section.innerHTML;
///////
var elem2=document.querySelector('#comments');
//2 add new #Modal
var new_Modal = template.content.querySelector('#comments #Modal');
elem2.appendChild(new_Modal);
//3 add new #pagination-nav
var new_pagination_nav = template.content.querySelector('#comments #pagination-nav');
elem2.appendChild(new_pagination_nav);
});
}
});
};
@ChathuraGH only the second page of comments will load, after which the link in the button will not change and the paginator disappears, it seems that this is the case - the paginator disappears and the number in the button does not change (
What is disappearing? the paginator disappears and the number in the button does not change? There is only one button. if it disappeared, how do you know "number in the button does not change"?
@ChathuraGH I added a button to the existing pagination, after loading one page the button disappears and an error appears:
newpost:2263 Uncaught (in promise) TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
here in this line:
elem2.appendChild(new_Modal);
I added a button to the existing pagination?
How did you do that?
{% load i18n %}
<nav id="pagination-nav" aria-label={% trans "Page navigation" %} class="mt-3 mb-5">
{% trans "Get More Comments" as Get_More_Comments %}
<ul class="pagination justify-content-center pagination-sm">
{% if comments.has_next %}
<li class="{{li_cls}}">
<a class="page-link {{text_style}}" onclick="event.preventDefault();Load_Commentsx(this);" href="?page={{ comments.next_page_number }}#comments" style="color:blue;font-weight:bold;font-size:large;" aria-label={{ Get_More_Comments }}>
{{ Get_More_Comments }}
</a>
</li class="{{li_cls}}">
{% endif %}
</ul>
</nav>
What parts did you include or exclude from above code?
I coded it to replace old template.
Just replace the content of the template. You can't use both(pagi number buttons and lode more button) with my js code.
@ChathuraGH I replaced all the code in the \Lib\site-packages\comment\templates\comment\comments\pagination.html file: here is the full code:
{% load i18n %}
<nav id="pagination-nav" aria-label={% trans "Page navigation" %} class="mt-3 mb-5">
{% trans "Get More Comments" as Get_More_Comments %}
<ul class="pagination justify-content-center pagination-sm">
{% if comments.has_next %}
<li class="{{li_cls}}">
<a class="page-link {{text_style}}" onclick="event.preventDefault();Load_Commentsx(this);" href="?page={{ comments.next_page_number }}#comments" style="color:blue;font-weight:bold;font-size:large;" aria-label={{ Get_More_Comments }}>
{{ Get_More_Comments }}
</a>
</li class="{{li_cls}}">
{% endif %}
</ul>
</nav>
<script type="text/javascript">
// with support to DAB version: v2.8.0 (last)(2023/12)
function Load_Commentsx(e){
var q_url=e.href;
let response = fetch(q_url).then(function(response) {
if (response.ok) {
response.text().then(function(text) {
// remove > #pagination-nav + #Modal
document.querySelector('#pagination-nav').remove();
document.querySelector('#Modal').remove();
// template
var template = document.createElement('template');
template.innerHTML = text;
// add new comments
var old_comments=document.querySelector('section#comments div.mt-5');
const new_comments_section= template.content.querySelector('section#comments div.mt-5');
old_comments.innerHTML = old_comments.innerHTML + new_comments_section.innerHTML;
///////
var elem2=document.querySelector('#comments');
//2 add new #Modal
var new_Modal = template.content.querySelector('#comments #Modal');
elem2.appendChild(new_Modal);
//3 add new #pagination-nav
var new_pagination_nav = template.content.querySelector('#comments #pagination-nav');
elem2.appendChild(new_pagination_nav);
});
}
});
};
</script>
When you click on the "load more" button, only the second page is loaded, after which the button disappears and an error appears in the console:
Uncaught (in promise) TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
at eeee:2206:15
bro I told you to put js code in your main template. not in pagination template.
1)
Put js code just inside template you are loading comments.
like after {% include_bootstrap %}.
@ChathuraGH placed in the template, a similar error after loading 2 pages:
Uncaught (in promise) TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
at eeee:2296:15
try to reproduce the error: create more than 3 pages of comments
@ChathuraGH it worked, it seems,
replaced the line
elem2.appendChild(new_Modal);
in
elem2.appendChild(document.createElement(new_Modal));
and delete line:
document.querySelector('#Modal').remove();
thanks for the help
@ChathuraGH I have several questions, the first one:
- Is it safe to insert content on the page (innerHTML) like this?
- How can a preloader be implemented?
- yes.
- you mean to load all comments at once?
@ChathuraGH I mean how to add a “loading..” animation, like for example on YouTube, when you click “Load comments” a preloader appears until the comments are loaded
It's easy.
- Download/creat your loading animation (image or gif or css)
- if it's image or gif add it to your static files / if it's css just use html
- append it like below
- remove it after successful load comments
<script type="text/javascript">
// with support to DAB version: v2.8.0 (last)(2023/12)
function Load_Commentsx(e){
var q_url=e.href;
// append your image/gif/css
if(document.querySelector('#loading')){
}
else{
var elem0=document.querySelector('#comments');
var new_Modal =document.createElement('your html with id==loading');
elem0.appendChild(new_Modal);
}
let response = fetch(q_url).then(function(response) {
if (response.ok) {
response.text().then(function(text) {
// remove > #pagination-nav + #Modal
document.querySelector('#pagination-nav').remove();
document.querySelector('#Modal').remove();
// template
var template = document.createElement('template');
template.innerHTML = text;
// add new comments
var old_comments=document.querySelector('section#comments div.mt-5');
const new_comments_section= template.content.querySelector('section#comments div.mt-5');
old_comments.innerHTML = old_comments.innerHTML + new_comments_section.innerHTML;
///////
var elem2=document.querySelector('#comments');
//2 add new #Modal
var new_Modal = template.content.querySelector('#comments #Modal');
elem2.appendChild(new_Modal);
//3 add new #pagination-nav
var new_pagination_nav = template.content.querySelector('#comments #pagination-nav');
elem2.appendChild(new_pagination_nav);
// Remove your image/gif/css
if(document.querySelector('#loading')){
document.querySelector('#loading').remove();
}
});
}
});
};
</script>
@ChathuraGH thanks for the help, i created
<div> <img src="https://media.tenor.com/G7LfW0O5qb8AAAAi/loading-gif.gif" id="loading"> </div>
add to scrpit to:
if(document.querySelector('#loading')){
}
else{
var elem0=document.querySelector('#comments');
var new_Modal =document.createElement('your html with id=loading');
elem0.appendChild(new_Modal);
}
// Remove your image/gif/css
if(document.querySelector('#loading')){
document.querySelector('#loading').remove();
}
erorr:
Uncaught DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('your html with id=loading') is not a valid name.
did do something wrong?
bro I actually can't believe you ran this line.var new_Modal =document.createElement('your html with id=loading'); ..
I will post working code.