yii2mod / yii2-comments

Comments module for Yii2
MIT License
158 stars 63 forks source link

Comments in modal window #24

Closed Gawran closed 8 years ago

Gawran commented 8 years ago

I used your extension to load comments in a modal window. It worked fine and the page is rendered correctly but after submitting new comment and after a "success" response the whole page is reloaded.

As far as I can say it happens because of the PJAX reload but I do not understand why the whole page gets reloaded instead of only PJAX container.

Any thoughts on this issue would be appreciated.

ihorchepurnyi commented 8 years ago

Hi, how i can reproduce your issue? Can you add your code here?

ihorchepurnyi commented 8 years ago

Try the following code:

use yii\bootstrap\Modal

Modal::begin([ 
    'header' => '<h2>Comments</h2>', 
    'toggleButton' => ['label' => 'View comments'], 
]); 

echo Comment::widget([ 
        'model' => $model, 
        'relatedTo' => 'cms page: ' . $model->url 
]); 

Modal::end()

It works for me wiithout reload the page.

Gawran commented 8 years ago

I am sorry I had to be more precise. I am using AJAX CRUD extension and a Kartik Tabx for tabs in modal window. This is my view file that is opened in a modal window:

``<?php use kartik\tabs\TabsX; $items = [ [ 'label'=>' Osnovni podaci', 'content'=>$this->renderAjax('_osnovniPodaci', [ 'model' => $model, 'types' => $types, 'statuses' => $statuses, 'priorities' => $priorities, 'users'=>$users, 'client'=>$client, 'creator'=>$creator ]), ], [ 'label'=>' Komentari', //here is the comments tab 'linkOptions'=>['data-url'=>\yii\helpers\Url::to(['comments', 'id'=>$model->id])] ], [ 'label'=>' Poslovi', 'content'=>$this->renderAjax('_jobs', [ 'model' => $model, 'types' => $types, 'statuses' => $statuses, 'priorities' => $priorities, 'users'=>$users, 'client'=>$client, 'creator'=>$creator ]), ], [ 'label'=>' Dokumenti', 'content'=>"Neki kontent", ], [ 'label'=>' Logovi', 'content'=>"Neki kontent", ], ];

echo TabsX::widget([
    'id' => 'tabs-tic-update',
    'items'=>$items,
    'position'=>TabsX::POS_ABOVE,
    'encodeLabels'=>false,
    'containerOptions'=>[
        'id'=>'global_tabs'
    ],
    'pluginOptions' => [
        'enableCache' => false
    ]
]);
?>

Tab for comments is loaded via Ajax but it does not make any problems. I did that only so I can reload whole tab from the controller. That seems too hacky to me. I had to change in comment.js part where it resets the form and reload pjax:

function beforeSubmitForm() {
        var $commentForm = $(this),
            settings = $commentForm.data('comment');
        //Add loading to comment button
        $commentForm.find(':submit').prop('disabled', true).text('Loading...');
        var pjaxSettings = $.extend({container: settings.pjaxContainerId}, settings.pjaxSettings);
        //Send post request
        $.post($commentForm.attr("action"), $commentForm.serialize(), function (data) {
            //If success is status, then pjax container has been reloaded and comment form has been reset
            if (data.status == 'success') {
                $('#global_tabs .active a').trigger('click');
//===>I've commented this out and added click event above to reload the ajax loaded tab. <====
               /* $.pjax(pjaxSettings).done(function () {
                    $commentForm.find(':submit').prop('disabled', false).text('Comment');
                    $commentForm.trigger("reset");
                    //Restart plugin
                    methods.reset.call($commentForm, settings);
                });*/
            }
            //If status is error, then only show form errors.
            else {
                if (data.hasOwnProperty('errors')) {
                    $commentForm.yiiActiveForm('updateMessages', data.errors, true);
                }
                else {
                    $commentForm.yiiActiveForm('updateAttribute', 'commentmodel-content', [data.message]);
                }
                $commentForm.find(':submit').prop('disabled', false).text('Comment');
            }
        });
        return false;
    }

The $.pjax().done() part reloads the whole page. Before that page receive "success" status with no problem and if that part is commented out page stays but comments are not updated.
ihorchepurnyi commented 8 years ago

Do I understand correctly that the comments widget renders via ajax request? Can you add your action code here?

Gawran commented 8 years ago

Yes. It is rendered via ajax. I n my controller I have just this:

`public function actionComments($id)
    {
        $model = $this->findModel($id);
        $html = $this->renderPartial('_comments', ['model'=>$model]);
        return Json::encode($html);
    }`

And in _comments.php:

`<?php

<div class="comments-form">
    <?php
    echo \yii2mod\comments\widgets\Comment::widget([
        'model' => $model,
        'relatedTo' => 'User ' . \Yii::$app->user->identity->user_name . ' commented on the page ' . \yii\helpers\Url::current(), // for example
        'maxLevel' => 3, // maximum comments level, level starts from 1, null - unlimited level. Defaults to `7`
        'showDeletedComments' => true, // show deleted comments. Defaults to `false`.
        'pjaxContainerId' => 'pjax-container-comm'
    ])
    ?>

</div>

`

ihorchepurnyi commented 8 years ago

ok, i test your code and write about the result later

ihorchepurnyi commented 8 years ago

The following code works for me: 1) Action:

    public function actionComments($id)
    {
        $model = CmsModel::findOne($id);
        $html = $this->renderAjax('comments', [
            'model' => $model
        ]);

        return Json::htmlEncode($html);
    }

2) View - comments.php:

<?php echo \yii2mod\comments\widgets\Comment::widget([
    'model' => $model,
    'relatedTo' => 'cms page: ' . $model->url,
    // the following code prevent reload the page
    'clientOptions' => [
          'pjaxSettings' => [
               'url' => \yii\helpers\Url::to(['/site/comments', 'id' => $model->id]),
               'timeout' => 10000,
               'scrollTo' => false,
               'enablePushState' => false
        ]
    ]
]);

3) Tabs code:

echo TabsX::widget([
            'items' => [
                [
                    'label' => 'Test',
                    'content' => 'some content',
                    'active' => true,
                ],
                [
                    'label' => 'Comments',
                    'linkOptions' => ['data-url' => \yii\helpers\Url::to(['/site/comments', 'id' => $model->id])]
                ],
            ],
            'position' => TabsX::POS_ABOVE,
            'encodeLabels' => false
        ]);
Gawran commented 8 years ago

It behaves the same. I can't really say where it tries to get content for pjax container from. As I said it successfully retrieve the "success" status from the actionCreate method but after it tries to rest the widget it reloads entire page. It hits the:

http://localhost/basic/basic/web/index.php?r=sqm%2Ftickets&_pjax=%23pjax-container-comm-7

and relaod the page.

On Tue, Aug 2, 2016 at 5:34 PM, Igor Chepurnoy notifications@github.com wrote:

You can try to delete the line 'pjaxContainerId' => 'pjax-container-comm' or set the unique pjaxContainerId for example

'pjaxContainerId' => 'comments-container-' . $model->id

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/yii2mod/yii2-comments/issues/24#issuecomment-236942916, or mute the thread https://github.com/notifications/unsubscribe-auth/AEv4-9c03TuUh0AUwInfzOPAcRgl5wgDks5qb2N5gaJpZM4JZlfG .

Sa poštovanjem, Miodrag Gavranov

ihorchepurnyi commented 8 years ago

Page reloads because the second request after comment has been added sends to the current url. Our goal is to change the url for the second request, which updates the container.

You need to define the pjaxSettings in your comments view:

echo \yii2mod\comments\widgets\Comment::widget([
    'model' => $model,
    'relatedTo' => 'cms page: ' . $model->url,
    'clientOptions' => [
          'pjaxSettings' => [
               'url' => \yii\helpers\Url::to(['comments', 'id'=>$model->id]), // this line overrides the second request
               'timeout' => 10000,
               'scrollTo' => false,
               'enablePushState' => false
        ]
    ]
]);
ihorchepurnyi commented 8 years ago

Also change your code in the action to the following:

    public function actionComments($id)
    {
        $model = $this->findModel($id);
        $html = $this->renderAjax('_comments', ['model'=>$model]);

        return Json::htmlEncode($html);
    }

renderAjax function is important!

Gawran commented 8 years ago

All right. We are getting somewhere now. Two remaining problems now are that I lose assets. CSS and JS are not loaded. And URL is changed no matter if enablePushState is true or false. I manually registered CommentAsset in my view file and that solved the assests problem. And I'll see what is causing the URL problem. Thank you a lot! Everything was of great help! I was stuck on this.

ihorchepurnyi commented 8 years ago

Maybe js and assets loses because you used the renderPartial function, try to change renderPartial on the renderAjax. When i used the renderPartial function i lose assets too.

And use the htmlEncode instead encode.

varmad commented 8 years ago

@igor-chepurnoi I want to do comments posting on the modal window, when I try above examples popup is closing after comment submit.

My code:

In Project controller

public function actionComments($id) {

        $model = Projects::findOne($id);

        return $this->renderAjax('comments', [
            'model' => $model
        ]);

 }

In comments view file

<?php echo \yii2mod\comments\widgets\Comment::widget([
            'model' => $model,
            'relatedTo' => 'User ' . \Yii::$app->user->identity->username . ' commented on the page ' . \yii\helpers\Url::current(), // for example
            'clientOptions' => [
                  'pjaxSettings' => [
                       'url' => \yii\helpers\Url::to(['comments', 'id' => $model->id]),
                       'timeout' => 10000,
                       'scrollTo' => false,
                       'enablePushState' => false
                ]
            ]

            // 'maxLevel' => 4, // maximum comments level, level starts from 1, null - unlimited level. Defaults to `7`
            // 'showDeletedComments' => false // show deleted comments. Defaults to `false`.
        ]); ?>

Please help me.

Thanks, Varma

ihorchepurnyi commented 8 years ago

@varmad Hi, please provide your full code here(popup, controller and view)

ihorchepurnyi commented 8 years ago

@varmad you can use the following code for render the comments widget in the popup:

use yii\bootstrap\Modal

Modal::begin([ 
    'header' => '<h2>Comments</h2>', 
    'toggleButton' => ['label' => 'View comments'], 
]); 

echo Comment::widget([ 
        'model' => $model, 
        'relatedTo' => 'cms page: ' . $model->url 
]); 

Modal::end()
varmad commented 8 years ago

Thanks @igor-chepurnoi it's working

valexus1 commented 6 years ago

hello! @igor-chepurnoi i've tried some solution without success...

i have for some reasons a foreach foreach ($dataProvider->models as $model)

and in footer of my page there is a single static html bootstrap modal, when i click to a photo - like instagram desktop - a js call an ajax request and populate the modal like

  $.ajax({
                    type: \'POST\',
                    url : "'.Url::to(['/wishlist/items/getmodal']).'",
                    data : {id: selectedId},
                    success: function(result){
                       $(".modal-body").html(result); 
                }});

in getmodal i insert this code

$modal .=  \yii2mod\comments\widgets\Comment::widget([
        'model' => $model,
        'relatedTo' => 'User ' . \Yii::$app->user->identity->username . ' commented on the page ' . \yii\helpers\Url::current(), 
        'clientOptions' => [
         'pjaxSettings' => [
        'url' => \yii\helpers\Url::to(['items/comments', 'id' => $model->id]),
        'formId' => 'comment-form2',
        'pjaxContainerId' => 'pjax-container-'.$model->id
                        ]
                    ]
                ]); 

well, when i open the modal i see the comments but nothing works - delete, reply (on click no js error but nothing happens..) - on submit form page goes to /default/create and i see the {"status":"success"}

what's wrong in my config? in my vendor -> itemscontroller

public function actionComments($id)
    {
        $model = Items::findOne($id);
        $html = $this->renderAjax('comments', [
            'model' => $model
        ]);

        return Json::htmlEncode($html);
    }
valexus1 commented 6 years ago

i've found the solution, in getmodal $modal .= $this->renderAjax('comments', [ 'model' => $model ]);

great work, thanks!

valexus1 commented 6 years ago

Hi ! sorry if i return to this discussion,

when i open for the first time the modal everything works fine, close and reopen the same and nothing works, delete and reply and the form go to page comment/default/create?entity...

in db the url is empty...

i have a page like instagram with a lot of photos and when someone click to a single photo an ajax call populate the modal, like i describe above..

in getmodal function i call a renderAjax and all the code populate the modal...

like

` $modal .=

somecodehere
; $modal .= $this->renderAjax('comments', [ 'model' => $model ]); return $modal; ` first time its ok everythings work fine, second call seems like some js var goes empty or i have to purge/refresh in someway some variable ? i don't know... while the previous modal does not work if i change photo - open it for the first time - the comments works... any kind suggestions? thanks..