Jump to content

FieldTypeComments - how to comment from parent page?


marie.mdna
 Share

Recommended Posts

Hi everyone, I am new to processwire and I love it so far but got a bit of challenges with the FieldTypeComments module. I have been working on a website that has groups, in each group members can post images, youtube video or plain text that will create a new child to the group (group-post). I have a basic form for this, filling the fields of the new page with the different inputs the members want to share. The idea is that members can also respond to someone else's post, hence those page children have the comment field from FieldTypeComments module.

(basically home/groups/group/group-post)

The pages having the group-post template aren't supposed to be accessed directly, only the page having the group template. All the content of their fields are called this way :

<!-- //group template  -->
<?php
//get children (group-post template)
foreach ($page->children->find("sort=-created") as $post ){

    echo $post->title;

    echo "<p class='CommentHeader'>";
    $post->of(false);
    $numTotal = $post->comments->count();
    if($numTotal <= 1){
        echo "{$numTotal} comment";
    }else{
        echo "{$numTotal} comments";   
    }
    echo "</p>";

    echo $post->body;

    if($post->get('comments')->count()){
        $list = $post->comments->getCommentList([
            'className' => 'CommentListCustom',
        ]); 

        $list->setMarkup([
            'noticeMessage' => "<div id='{id}' class='uk-alert {class}'>{message}</div>",
            'noticeSuccessClass' => 'uk-alert-success',
            'noticeErrorClass' => 'uk-alert-danger',
            'list' => "<ul id='my-comments-list' class='{class}'>{comments}</ul>", 
            // and so on for any other $markup properties
        ]); 

        echo $list->render();
    }else{
        echo"<small><p style='text-align:center;'>No comment yet, be the first!</p></small>";
    }

    $form = $post->comments->getCommentForm([
        'className' => 'CommentFormCustom',
    ]);

    $formMarkup = "
    <form class='{form.class} discussions_message ' id='my-comment-form' action='{form.action}' method='{form.method}' {form.attrs}>
                <div class='avatar'>";

    if(count($user->images)){ //profile image for the user since I am not using gravatar
        $imgUrl = $user->images->last()->url;
    } else{ 
        $imgUrl = $user->url;
    } 
    $formMarkup .= "<img src='{$imgUrl}' data-src='{$imgUrl}'>";

    $formMarkup .= "
                </div> 

                <p class='{cite.wrap.class}'>
					<label class='{label.class}'>
						<span class='{label.span.class}'>{cite.label}</span> 
                        <textarea name='{cite.input.name}'  class='{cite.input.class}' required='required' value='{cite.input.value}' >{cite.input.value}</textarea>
					</label>
				</p>

				<p class='{email.wrap.class}'>
					<label class='{label.class}'>
						<span class='{label.span.class}'>{email.label}</span> 
                        <textarea name='{email.input.name}' class='{email.input.class}' required='required' value='{email.input.value}' >{email.input.value}</textarea>


					</label>
				</p>

				{if.website}
				<p class='{website.wrap.class}'>
					<label class='{label.class}'>
						<span class='{label.span.class}'>{website.label}</span> 
						<input type='text' name='{website.input.name}' class='{website.input.class}' value='{website.input.value}' maxlength='255' />
					</label>
				</p>
				{endif.website}

				{if.stars}
				<p class='{stars.wrap.class}' {stars.wrap.attrs}>
					<label class='{label.class}'>
						<span class='{label.span.class}'>{stars.label}</span> 
						{stars.markup}	
					</label>
				</p>
				{endif.stars}

				{if.honeypot}
				<p class='{honeypot.wrap.class}'>
					<label>
						<span>{honeypot.label}</span>
						<input type='text' name='{honeypot.input.name}' value='{honeypot.input.value}' size='3' />
					</label>
				</p>
				{endif.honeypot}

				<p class='{text.wrap.class}'>
					<label class='{label.class}'>
						<textarea style='border: 1.5px solid !important;' name='text' class='{text.input.class} my-comment my-new-comment' required='required' rows='{text.input.rows}' cols='{text.input.cols}'>{text.input.value}</textarea>
					</label>
				</p>

				{if.notify}
				<p class='{notify.wrap.class}'>
					<label class='{notify.label.class}'>
						<span class='{notify.label.span.class}'>{notify.label}</span>
					</label> 
					<label class='{notify.input.label.class}'>
						<input class='{notify.input.class}' type='radio' name='{notify.input.name}' checked='checked' value='{notify.input.off.value}' {notify.input.off.checked}/> 
						{notify.input.off.label}
					</label>	

					{if.notify.replies}
					<label class='{notify.input.label.class}'>
						<input class='{notify.input.class}' type='radio' name='{notify.input.name}' value='{notify.input.replies.value}' {notify.input.replies.checked}/> 
						{notify.input.replies.label}
					</label>	
					{endif.notify.replies}

					{if.notify.all}
					<label class='{notify.input.label.class}'>
						<input class='{notify.input.class}' type='radio' name='{notify.input.name}' value='{notify.input.all.value}' {notify.input.all.checked}/> 
						{notify.input.all.label}
					</label>	
					{endif.notify.all}
				</p>	
				{endif.notify}

				<p class='{submit.wrap.class}'>
					<button type='submit' class='{submit.input.class} button' name='{submit.input.name}' value='{submit.input.value}'>Reply</button>
					{form.hidden.inputs}
				</p>
			</form>
  ";

    $form->markup('form', $formMarkup);
    $form->labels('submit', 'Submit Feedback');
    $form->labels('notify', 'Email Me');

    // form notifications
    $form->markup('notification', "<div class='uk-alert {class}'>{message}</div>");
    $form->classes('success', 'uk-alert-success');
    $form->classes('pending', 'uk-alert-warning');
    $form->classes('error', 'uk-alert-danger');

    echo $form->render();

}
?>

I use the comment module on different templates that have different behaviors. It works so perfectly when the comment field is on the page receiving comments, but for the case of my group-post the comments are added from the group template to the group-post template. It actually works fine when the group only has 1 child, votes included, however, when there is multiple children the comments are always adding up to the last group-post created.

I am worried to touch the module itself since I am still starting with ProcessWire modules and I don't want to mess up in anything before asking a bit of help, I am more than aware that this might be an unusual use of the FieldTypeComments module...

 

Does someone ever had this issue and found a way to keep my other comment field commenting the page there are on, but making sure that the group-post comments are adding in the right group-post child?

 

Sorry if it feels messy, and let me know if you need something else for giving some clues ?

Any help would be greatly appreciated!

Link to comment
Share on other sites

Welcome to the PW forums @marie.mdna!

I suspect that the problem is caused by the wrong page ID being set in the hidden page_id field of the comment form.

2022-05-28_090634.png.4da297729642053ddc0dc293bc328cd6.png

You could try manually setting the hidden fields by replacing...

2 hours ago, marie.mdna said:
{form.hidden.inputs}

...with...

<input type='hidden' name='page_id' value='{$post->id}' />
<input type='hidden' class='CommentFormParent' name='parent_id' value='0' />

 

Link to comment
Share on other sites

Thank you @Robin S for your very fast answer and for the welcoming!

I also thought so but the ID are different for each comment form on the current version, would there be a way to double check the post request before it is actually sent?

1331440936_Capturedcran2022-05-2723_15_46.thumb.png.19c68b7994eef40dc88daa61c055b0e4.png

They currently all get sent on the one with the id 1230...

637657190_Capturedcran2022-05-2723_16_15.thumb.png.73c04943f050376da491bd1b115c3c40.png

472708011_Capturedcran2022-05-2723_16_44.thumb.png.f2ceea517832ae5e4a26dd81dbbe605e.png

For example, here are the other two ones I have been testing my page with.

Link to comment
Share on other sites

Hi @Robin S, I tried to double check with the renderSuccess function redirect.

I had a different redirect setting in the CommentForm.php file for the comments to prevent redirecting to children pages in case there was some, I put it back as it was originally to test :

<?php
protected function renderSuccess(Comment $comment = null) {

        $pageID = (int) $this->wire('input')->post('page_id'); 

        if($pageID && $this->options['redirectAfterPost']) {
            // redirectAfterPost option
            $page = $this->wire('pages')->get($pageID); 
            if(!$page->viewable() || !$page->id) $page = $this->wire('page');
            $url = $page->id ? $page->url : './';
            $url .= "?comment_success=1";
            if($comment && $comment->id && $comment->status > Comment::statusPending) {
                $url .= "&comment_approved=1#Comment$comment->id";
            } else {
                $url .= "#CommentPostNote";
            }
            $this->wire('session')->set('PageRenderNoCachePage', $page->id); // tell PageRender not to use cache if it exists for this page
            $this->wire('session')->redirect($url);
//          $this->wire('session')->redirect("./#"); //_________________added ffor my website
            return '';
        }
?>

it is actually really redirecting to the right page:

http://localhost:888/groups/group/group-post-id-1218/?comment_success=1&comment_approved=1#Comment68

but adding to the wrong one:

1866579870_Capturedcran2022-05-2811_16_09.thumb.png.1619a872843aa66bba17cbd43d502c04.png

Link to comment
Share on other sites

@marie.mdna, I tested and can confirm the problem when there are multiple comment forms relating to different pages all rendered on the same page. I'm not sure if FieldtypeComments is intended to support that sort of use but I don't see why it shouldn't. I suggest opening a GitHub issue for this so Ryan can take a look.
https://github.com/processwire/processwire-issues/issues

  • Like 2
Link to comment
Share on other sites

@Robin S thank you for taking time to test is out, I will  forward the issue on GitHub.

 

Meanwhile, if this can't get a fix, I have been thinking about an alternative solution, but there is some more questions to it.

I could get rid of the group-post template and giving the comment field to the group template. It would then bring only one comment form to the page and the "group-post" would then be comments with depth. My only concern would be for two kinds of inputs that would have to be added as custom fields for the form : images and page reference.

I saw I can add the youtube link field by adding another URL field similar to the website field already existing in the comment form.

https://processwire.com/talk/topic/760-add-a-url-field-to-the-comments-form/#comment-6346

But I am not sure about the difficulty when it comes to add images and page reference fields... 

 

Here is my current form for creating the group-post child as an example of the expected behavior:

<?php
if($input->post->post) {

    $upload_path = $config->paths->assets . "files/temp/";

    $contact_photo = new WireUpload('contact_photo'); // References the name of the field in the HTML form that uploads the photo
    $contact_photo->setMaxFiles(1);
    $contact_photo->setOverwrite(false);
    $contact_photo->setDestinationPath($upload_path);
    $contact_photo->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif'));

    // execute upload and check for errors
    $files = $contact_photo->execute();

//removed because this input isn't required
    // Run a count($files) test to make sure there are actually files; if so, proceed; if not, generate getErrors()
    //            if(!count($files)) {
    //                $contact_photo->error("Sorry, but you need to add a photo!");
    //                return false;
    //            }
    $theUser = $user->name;
    $contentText = $input->post->body;
    $short = strlen($contentText) > 20 ? substr($contentText,0,20)."..." : $contentText;
    $whatType = $input->post->type;

    $p = new Page();
    $p->template = "group-post";
    $p->parent = $page->url;
    $p->title = $theUser . " - " . $whatType . " - " . $short;
    $p->types = $input->post->type;
    $p->youtube = $input->post->youtube;
    $p->body = $input->post->body;
    $p->save();

    $p->title = $sanitizer->text($theUser . " - " . $whatType . " - " . $short);
    $p->youtube = $sanitizer->text($input->post->youtube);
    $p->types = $sanitizer->checkbox($input->post->type);
    $p->body = $sanitizer->textarea($input->post->body);
    $p->save();

    foreach($files as $filename) {
        $pathname = $upload_path . $filename;
        $p->images->add($pathname);
        $p->message("Added file: $filename");
        unlink($pathname);
    }
    $p->save();

    //        $session->redirect("./" . $sanitizer->pageName($post->titre, true));
    $session->redirect("./");

    return true;


}
?>
<form action="./" method="post"  enctype="multipart/form-data">
    <div id="my-comment-form" class="discussions_message">
        <div class='avatar'>
            <?php        
// user image instead of gravatar
				if(count($user->images)){ 
    				$imgUrl = $user->images->last()->url;
				} else{ 
 				   $imgUrl = $user->url;
				} 
            ?>    

            <img src='<?php echo $imgUrl; ?>' data-src='<?php echo $imgUrl; ?>'>
        </div>
        <div class="infos">
            <p class='CommentFormText CommentForm_text'>
                <textarea class='my-comment' name="body" rows="5" cols="50"></textarea>
            </p>
            <div class="radio-toolbar small CommentFormText CommentForm_text">
                <?php
//the page reference input, I use them as tags for a search on the page
                $types = $pages->get('types');
                foreach($types->children as $type){
                    echo "<input class='tags' type='radio' id='tag{$type->title}' name='type'  value='{$type->title}'/><label for='tag{$type->title}'>#{$type->title}</label>";
                }
                ?>
            </div>
            <div class="uploads flex-top CommentFormText CommentForm_text">
                <div class="image-upload">
                    <label  for="upload-image">Upload your image</label>
                    <input id="upload-image" class="photo-button" type="file" name="contact_photo" hidden/>
                    <span id="file-chosen">No image chosen</span>
                </div>
                <div class="button">or</div>
                <div class="youtube-upload radio-toolbar small">

                    <input name="youtube" placeholder="Share a youtube video...">
                </div>
            </div>


        </div>
        <input id='post-button' type="submit" name="post" value="Post">
    </div>

    <script>
  // showing the name of the selected image
        const actualBtn = document.getElementById('upload-image');

        const fileChosen = document.getElementById('file-chosen');

        actualBtn.addEventListener('change', function(){
            fileChosen.textContent = this.files[0].name;
        })
    </script>
</form>

 

Thank a lot for your help so far! I really appreciate!

Link to comment
Share on other sites

13 hours ago, marie.mdna said:

My only concern would be for two kinds of inputs that would have to be added as custom fields for the form : images and page reference.

I don't think FieldtypeComments will be able to support those because they require their own dedicated fieldtypes to hold the data. So you would need to create a custom form to handle those, and if the images / page reference needs to be connected with individual comments then you probably need a totally custom comments implementation where you use a page-per-comment behind the scenes.

But coming back to the original issue: one way you could work around this is to list all the comments on the parent page, but if a person wants to add a comment they click a link to submit the comment on the child page. If that child page should only be used to submit a comment and not to display any other information then you could use a URL parameter (or alternatively a URL segment) in the link and if the page is loaded without that parameter it redirects back to the parent page.

So in the parent page template:

<?php foreach($page->children as $child): ?>
	<h3><?= $child->title ?></h3>
	<?= $child->comments->render() ?>
	<a href="<?= $child->url ?>?submit_a_comment=1">Submit a comment</a>
<?php endforeach; ?>

And in the child page template:

<h3>Submit a comment</h3>
<?php
// Show the comment form
echo $page->comments->renderForm();
// If the submit_a_comment URL parameter is not present then redirect to parent page
// This must go after the form render so that comment submissions will be processed before redirecting
if(!$input->get('submit_a_comment')) $session->redirect($page->parent->url);
?>

 

  • Like 1
Link to comment
Share on other sites

@Robin S thank you so much for your detailed answer!

Your solution works nicely thank you , I have been wondering if using an ajax function would be a smart idea to prevent seeing the group-post page at all... I will give it a try shortly but will keep this solution in case I can't make it.

  • Like 1
Link to comment
Share on other sites

Quick update! Thanks to your suggestion @Robin S, I could make it work without having to redirect to the child page.

Here is the adjustments I came up with, I changed the action of the form to 

action='{$post->url}?submit_a_comment=1'

Parent page template:

<?php
$form = $post->comments->getCommentForm([
    'className' => 'CommentFormCustom',
]);


$formMarkup = "
    <form class='{form.class} discussions_message ' id='my-comment-form' action='{$post->url}?submit_a_comment=1' method='{form.method}' {form.attrs}>
                <div class='avatar'>";


//        just added
if(count($user->images)){ 
    $imgUrl = $user->images->last()->url;
} else{ 
    $imgUrl = $user->url;
} 
$formMarkup .= "<img src='{$imgUrl}' data-src='{$imgUrl}'>";
//        end

$formMarkup .= "
                </div> 

                <p class='{cite.wrap.class}'>
					<label class='{label.class}'>
						<span class='{label.span.class}'>{cite.label}</span> 
                        <textarea name='{cite.input.name}'  class='{cite.input.class}' required='required' value='{cite.input.value}' >{cite.input.value}</textarea>
					</label>
				</p>

				<p class='{email.wrap.class}'>
					<label class='{label.class}'>
						<span class='{label.span.class}'>{email.label}</span> 
                        <textarea name='{email.input.name}' class='{email.input.class}' required='required' value='{email.input.value}' >{email.input.value}</textarea>


					</label>
				</p>

				{if.website}
				<p class='{website.wrap.class}'>
					<label class='{label.class}'>
						<span class='{label.span.class}'>{website.label}</span> 
						<input type='text' name='{website.input.name}' class='{website.input.class}' value='{website.input.value}' maxlength='255' />
					</label>
				</p>
				{endif.website}

				{if.stars}
				<p class='{stars.wrap.class}' {stars.wrap.attrs}>
					<label class='{label.class}'>
						<span class='{label.span.class}'>{stars.label}</span> 
						{stars.markup}	
					</label>
				</p>
				{endif.stars}

				{if.honeypot}
				<p class='{honeypot.wrap.class}'>
					<label>
						<span>{honeypot.label}</span>
						<input type='text' name='{honeypot.input.name}' value='{honeypot.input.value}' size='3' />
					</label>
				</p>
				{endif.honeypot}

				<p class='{text.wrap.class}'>
					<label class='{label.class}'>
						<textarea style='border: 1.5px solid !important;' name='text' class='{text.input.class} my-comment my-new-comment' required='required' rows='{text.input.rows}' cols='{text.input.cols}'>{text.input.value}</textarea>
					</label>
				</p>

				{if.notify}
				<p class='{notify.wrap.class}'>
					<label class='{notify.label.class}'>
						<span class='{notify.label.span.class}'>{notify.label}</span>
					</label> 
					<label class='{notify.input.label.class}'>
						<input class='{notify.input.class}' type='radio' name='{notify.input.name}' checked='checked' value='{notify.input.off.value}' {notify.input.off.checked}/> 
						{notify.input.off.label}
					</label>	

					{if.notify.replies}
					<label class='{notify.input.label.class}'>
						<input class='{notify.input.class}' type='radio' name='{notify.input.name}' value='{notify.input.replies.value}' {notify.input.replies.checked}/> 
						{notify.input.replies.label}
					</label>	
					{endif.notify.replies}

					{if.notify.all}
					<label class='{notify.input.label.class}'>
						<input class='{notify.input.class}' type='radio' name='{notify.input.name}' value='{notify.input.all.value}' {notify.input.all.checked}/> 
						{notify.input.all.label}
					</label>	
					{endif.notify.all}
				</p>	
				{endif.notify}

				<p class='{submit.wrap.class}'>
					<button type='submit' class='{submit.input.class} button' name='{submit.input.name}' value='{submit.input.value}'>Reply</button>
					{form.hidden.inputs}
				</p>
			</form>
  ";

$form->markup('form', $formMarkup);
$form->labels('submit', 'Submit Feedback');
$form->labels('notify', 'Email Me');

// form notifications
$form->markup('notification', "<div class='uk-alert {class}'>{message}</div>");
$form->classes('success', 'uk-alert-success');
$form->classes('pending', 'uk-alert-warning');
$form->classes('error', 'uk-alert-danger');

echo $form->render();


?>

Child page template:

<?php
// Show the comment form
echo $page->comments->renderForm();

// If the submit_a_comment URL parameter is not present then redirect to parent page
// This must go after the form render so that comment submissions will be processed before redirecting
if(!$input->get('submit_a_comment')) 
    $session->redirect($page->parent->url);
?>

Comments are now adding to the right child without redirecting! Thank you so much for your time and help. This community is amazing!

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...