comments icon indicating copy to clipboard operation
comments copied to clipboard

Custom Templates but default JS

Open pimago opened this issue 1 year ago • 5 comments

Question

Hi, is it possible to use custom templates with craft.comments.fetch() but still use the default JS?

Additional context

Just leaving the setting on for JS doesn't work. I found craft.comments.renderJs(), but it looks like it only works with craft.comments.render()?

pimago avatar Nov 17 '24 11:11 pimago

You certainly can BYO templates if you like, but you still need to have certain markup to hook up to Comments' JS.

{# Render the `comments.js` file - exclude the inline JS that initializes the instance #}
{{ craft.comments.renderJs(entry.id, {}, false) }}

{# Fetch the variables required for the comments JS #}
{% set jsVariables = craft.comments.getJsVariables(entry.id) %}

{# Minimal markup to get you going (doesn't include everything) #}
<div id="cc-w-{{ entry.id }}">
    <div data-role="comments">
        {% for comment in craft.comments.fetch().owner(entry).all() %}
            <article id="comment-{{ comment.id }}" data-id="{{ comment.id }}" data-site-id="{{ comment.siteId }}" data-role="comment" itemprop="comment" itemscope itemtype="http://schema.org/UserComments">
                <div data-role="wrap-content">
                    <div data-role="content">
                        <div data-role="body">
                            <div data-role="message" dir="auto" itemprop="commentText">
                                <p>{{ comment.comment | nl2br }}</p>
                            </div>
                        </div>
                    </div>

                    <div data-role="reply"></div>

                    <div data-role="errors"></div>
                    <div data-role="notice"></div>
                </div>
            </article>
        {% endfor %}

        <article data-role="form">
            <form role="form" method="post" accept-charset="UTF-8">
                <input type="hidden" name="action" value="comments/comments/save">
                <input type="hidden" name="elementId" value="{{ entry.id }}">
                <input type="hidden" name="siteId" value="{{ entry.siteId }}">
                {{ craft.comments.protect() }}
                {{ csrfInput() }}

                <textarea name="fields[comment]" placeholder="Add a comment..." required></textarea>

                <div data-role="notice"></div>

                <button type="submit">{{ 'Post comment' | t('comments') }}</button>
            </form>
        </article>
    </div>
</div>

{# Wait for the document to be ready, then initialise #}
{% js %}
    document.addEventListener('DOMContentLoaded', function() {
        // Populate the ID and the settings
        new Comments.Instance('{{ jsVariables.id }}', {{ jsVariables.settings | json_encode | raw }});
    });
{% endjs %}

The HTML above is just a bare-bones example, it doesn't contain everything like avatars, nested comments, replies, etc. That's too much for one file, and why we split them out into multiple includes.

I'd still probably recommend template overrides just because you otherwise have to template everything from scratch. Because while the above works, it's going to load in the Twig for the new comment to be inserted via JS, and it'll use the template you specify. It's for this reason I'd really suggest using template overrides, which allows you to tell Comments which templates to use.

Then, you've got total control over the markup, provided you just add those data attributes (data-role are typically what's used to hook things up).

engram-design avatar Nov 17 '24 23:11 engram-design

Thanks. I will try that! I am currently using overrides, but the js wasn't working anymore.

pimago avatar Nov 18 '24 06:11 pimago

It's working, but not fully. The reason I am using fetch instead of render is so I can load more comments with Sprig.

The JS is only working for the initially loaded comments. Could there something that might be missing on the comments that are loaded later with sprig? The mark up is looking good, and I do not get any errors. Instead of opening the reply form the links just do their # href.

pimago avatar Nov 19 '24 07:11 pimago

That sounds like it probably won't work with our JS, as it won't work for dynamically loaded items. You essentially need to call Comments.Instance() after every "load more" so that new comments lazy-loaded in are initialised. The Comments' JS doesn't have a convenient per-comment init function, just the overall container to initialize any comments within it.

engram-design avatar Nov 19 '24 22:11 engram-design

Alright. Thank you.

pimago avatar Nov 20 '24 05:11 pimago