DEV Community


Posted on • Updated on

Headless WordPress + Sapper Comments on Posts (Part 2)

#1 fetching the comments

The _embed query gets comments, featured image and few other optional properties of the blog post


{#if post._embedded.replies}
     {#each post._embedded.replies[0] as comment}
    <div class="comment-item">
      <div class="author-meta">
        <img src={comment.author_avatar_urls["96"]} alt={comment.author_name}>
        <span>{comment.author_name} <a href={comment.author_url}>{comment.author_url}</a></span>
        {@html comment.content.rendered}
    <p>No commets yet :D but you could write one</p>
Enter fullscreen mode Exit fullscreen mode

Iterating post._embedded.replies[0]this should list out all the comments and it should be populated in the frontend


#2 Posting/Submitting comment from Sapper

Sanity Check before posting comments or you would get this particular error.

{"code":"rest_comment_login_required","message":"Sorry, you must be logged in to comment.","data":{"status":401}}
Enter fullscreen mode Exit fullscreen mode

To resolve this we need to modify functions.php located in your server at /wp-content/themes/twentytwenty twentytwenty is the theme I am using so if you are using some other theme then go to it's respective folder.

add this immediately after all the comments/meta

add_filter( 'rest_allow_anonymous_comments', '__return_true' );
Enter fullscreen mode Exit fullscreen mode
Snippet from Cannot Comment Without Being Logged In #2960

#3 Testing with Postman

The comment API URL https://your-domain/wp-json/wp/v2/comments
needs a valid author_name, author_email, content (User comment), post (post id) without which you will face 4XX errors.

Since export let post; contains data of the post from the current page will get you the id of the post, in my case it is 8

Comment from Postman

#4 Posting via Sapper

Three input fields and a textarea to meet the API criteria for posting a comment.

    let name, email, url, comment = ''

    let formerrors;
    let commentSuccess = false;
    async function handleSubmit(e) {

        let formdata = new FormData();
        formdata.append("author_name", name);
        formdata.append("author_email", email);
        formdata.append("author_url", url ? url : '');
        formdata.append("content", comment);

        let requestOptions = {
            method: 'POST',
            body: formdata,

        fetch(`${process.env.SAPPER_APP_API_URL}/comments`, requestOptions)
            .then(response => response.json())
            .then(result => {
                if (result.code == "rest_comment_content_invalid") {
                    formerrors = result.message;

                if (result.code == "rest_invalid_param") {
                    formerrors =;
                } else {
                    commentSuccess = true;
                    name, email, url, comment = ''
                return result;
            .catch(error => console.log('error', error));
Enter fullscreen mode Exit fullscreen mode

Then the svelte part of the comment

<form on:submit|preventDefault={handleSubmit}>
        <input class="form-input" type="text" name="name" placeholder="Name" required bind:value={name}> 
        <input class="form-input" type="email" name="email" placeholder="Email" required bind:value={email}>
        <input class="form-input" type="text" name="url" placeholder="Website" bind:value={url}>

        <textarea name="comment" cols="30" rows="10" bind:value={comment}></textarea>
        <button type="submit">Submit</button>
        {#if formerrors}
        <p class="errors">{formerrors}</p>
        {:else if commentSuccess} 
        <p class="success">Comment has been submitted and held for approval</p>
Enter fullscreen mode Exit fullscreen mode

WordPress also returns validation errors on all input fields so you can handle them however you wish, the above example just shows the error.

Thank you for reading through the tutorial, Next part will cover fetching pages from WordPress.

Top comments (0)