Yii2 Pjax delete action with modal

I’m trying to do a delete action with Pjax (without refreshing the page).

The register is deleted properly, page no reloads, BUT, if immediately I try to delete another record, don’t load the modal. So the delete button cannot call to modal for new delete.

I hope you can help me to resolve this. Thanks

Here is my code:

Step 1

file: index view

<?php Pjax::begin(['id' => 'pjax-container']); ?>
      <?=

      GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
     .....
    'columns' => [
     ...others columns
    [
                'class' => 'yii\grid\ActionColumn',
                'template' => '{view} {delete}',
                'buttons' => [
'delete' => function ($url, $model, $key) {
                        return Html::a(
                                        '<span class="material-icons">delete</span>',
                                        'javascript:void(0)',
                                            [
                                                'data-ruta' => Url::toRoute(['delete', 'id' => $model->id]),
                                                'id' => $model->id,
                                                'class' => 'btn-eliminar-competencia option-danger',
                                                'title' => __('GxP', 'commons.delete'),
                                                'aria-label' => "Eliminar",
                                                'data-pjax' => "0",
                                                'data-method' => "post"
                                            ]
                                    ) . '</div>';
                    }
]

            ]
        ]
    ]);

    ?>
<?php Pjax::end(); ?>

Step 2

file index view

After clicking the delete button, go to open modal

<div class="modal bootstrap-dialog" role="dialog" aria-hidden="true" id="modal-eliminar- 
 competencia" aria-labelledby="w3_title" tabindex="-1">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                    <h4 class="modal-title"><?= __('GxP', 'commons.delete') ?></h4>
                </div>
                <div class="modal-body text-center">
    
                    <div class="bootstrap-dialog-message"><?= __('GxP', 'dialogs.sure_delete_element') ?></div>
                    <div id="text-modal-competencia"></div>
    
                </div>
                <div class="modal-footer text-center">
    
                    <button class="btn btn-success" data-dismiss="modal">
                        <?= __('GxP', 'commons.cancel') ?>
                    </button>
                    <button class="btn btn-primary btn-modal-eliminar-competencia">
                        <?= __('GxP', 'commons.accept') ?>
                    </button>
    
                </div>
            </div>
        </div>
    </div>

Step 3

file: index.js

$(document).ready(function(){
    var ruta
    eliminar = 0
    redirect = 0


    modal = $('#modal-eliminar-competencia')
    modal_competencia = $('#modal-competencia')
    $('.div2').click(function(){
        window.location = $('#tipos-competencias').attr('href')
    })

    $('.btn-eliminar-competencia').click(function(){
        eliminar = $(this).attr('data-ruta')
        $('#text-modal-competencia').html('')
        id = $(this).attr('id')
        $.ajax({
            type:'post',
            url:'/competences/competences-asociated',
            data:{id:id},
            dataType:'json'
        })
        .done(function(r){
            console.log(r)
            mensaje_text =  
                                '<br>'+
                                '<p>'+__('commons.info')+':</p>'+
                                '<small>'+
                                    r.positions+__('dialogs.associated_positions')+
                                '</small>'+
                                '<br>'+
                                '<small>'+
                                    r.reagents+__('dialogs.associated_reagents')+
                                '</small>';

            $('#text-modal-competencia').html(mensaje_text)
        })
        .fail(function(){
            
        }) 

        modal.modal({backdrop:'static',keyboard:true})
    })


// here resolve the delete item and reload container with Pjax

    $('.btn-modal-eliminar-competencia').click(function(){
        $.ajax({
            type:'post',
            url:eliminar,
            dataType:'json',
            success:function(response){
                if(response.code == 204){
                    redirect = response.redirect
                    $('.message-contenido .message-text').html(__('dialogs.success_delete'))
                    modal.modal('hide')
                    $('.capa').show()
                    $('.message-action').show()
                    ruta = false
                    $.pjax.reload({container:'#pjax-container'})
                }
                else{
                    modal_alert(__('dialogs.unespected_error'))
                }
            }
        })
    })

})

#yii-2-0 #Pjax

Does this help?

Hi @evstevemd
I’ve seen the post you shared with me, but it does not work such as I thought.
In my code, I have the delete-modal with ok-cancel options, inside the same index file.
and confirmation action is in another file called index.js
inside here I fill the body message of the confirmation modal, and reload Pjax container.
Is there any way to reload those buttons while items are deleted? That Could be work

It is hard for me to guess what you thought. The best way is incorporate the code in your code and then ask about exact part that is missing with new example code

Try changing this

$('.div2').click(function(){ .. });

to

$('.div2').on('click', function(){ ... });

And

$('.btn-eliminar-competencia').click(function(){ .. });

to

$('.btn-eliminar-competencia').on('click', function(){ .. });

and

$('.btn-modal-eliminar-competencia').click(function(){ .. });

to…

$('.btn-modal-eliminar-competencia').on('click`, function(){ ... });

on works with dynamic content

hi Shaho

I really appreciate your help. I did the changes as you mention, but I get the same result. Delete one item. and then, modal no load again.

regadards

does this work when you click? any errors in console? and does the pjax refresh after the 1st delete?

yes. Item is deleted and also table widget (this already were working), so nothing has changes.

console no returns error messages
after delete item, I proceed to delete the next, and and modal no loads (without error messages).
If you need more info, code, please ask me

Thanks for your time

Hi @fmoraless

This won’t work for the 2nd time, because the delete buttons with class="btn-eliminar-compentencia" have been overwritten by the 1st PJAX call and have lost the event handler.

The solution is to attach the event handler to an ancestor DOM object outside the PJAX updated area.

   $('#pjax-container').on('click', '.btn-eliminar-competencia', click(function(){

You may change $('#pjax-container') to $('body') or anything that is an ancestor of the delete buttons and is outside the PJAX area. In this way, the click events of the delete buttons will be handled by the PJAX-free event handler attached to the ancestor.

I understand the idea, but I can’t get to the solution.
I only did this change and I don’t have the expected results. surely something is wrong with my code,.

$('#pjax-container').on('click','.btn-modal-eliminar-competencia').click(function(){
		$.ajax({
			type:'post',
			url:eliminar,
			dataType:'json',
			success:function(response){
				if(response.code == 204){
					redirect = response.redirect
					$('.message-contenido .message-text').html(__('dialogs.success_delete'))
					modal.modal('hide')
					$('.capa').show()
        			$('.message-action').show()
        			ruta = false
        			$.pjax.reload({container:'#pjax-container', async:false})
				}
				else{
					modal_alert(__('dialogs.unespected_error'))
				}
			}
		})
	})

thanks

You got me wrong. I said:

$('#pjax-container').on('click', '.btn-eliminar-competencia',

The selector '.btn-modal-eliminar-competencia' refers to a button inside the modal, and it is not in the PJAX area. You don’t have to touch it. Or, exactily saying, you can not attach an event handler of this button to $(#pjax-container), because it is not a descendant of $('#pjax-container').

your syntax is wrong

$('#pjax-container').on('click','.btn-modal-eliminar-competencia', function(){ ...

https://api.jquery.com/on/

1 Like

You’re right.
I’ve made a mistake in my reply.
I’m very sorry > @fmoraless

1 Like

Hi @shaho

I did the modification, and now the modal confirmation button no has action. If is clicked, don’t do any action. so don’t make the item delete.
something is missing, but I don’t know what is.

$('#pjax-container').on('click','.btn-modal-eliminar-competencia',function(){
		$.ajax({
			type:'post',
			url:eliminar,
			dataType:'json',
			success:function(response){
				if(response.code == 204){
					redirect = response.redirect
					$('.message-contenido .message-text').html(__('dialogs.success_delete'))
					modal.modal('hide')
					$('.capa').show()
        			$('.message-action').show()
        			ruta = false
        			$.pjax.reload({container:'#pjax-container', async:false})
				}
				else{
					modal_alert(__('dialogs.unespected_error'))
				}
			}
		})
	})

I appreciate all your comments
thanks

If the modal is outside the PJAX area, this won’t work because the click event of the button won’t bubble up to $('#pjax-container')

Try this instead:

`$('.btn-modal-eliminar-competencia').on('click',function(){`

or

`$('body').on('click','.btn-modal-eliminar-competencia', function(){`

I’m sorry for disappointing you, but I’ve returned to the beginning.
Item is deleted, page no refresh, try to delete a second item. modal no load.

This is my current code with your tips and modifications suggested. I’ve incorporated the controller method, and code when the modal is closed.
index view
https://codeshare.io/OdYRy7

index.js
https://codeshare.io/oQlNjY

controller /(delete function)

public function actionDelete($id)
    {
        $this->findModel($id)->delete();

        return json_encode([ 'code' => 204 ]);

    }

Thanks again

index.js line 19

This must be

	$('#pjax-container').on('click', 'btn-eliminar-competencia', function(){
1 Like

This may not be the best solution but it seems to work
Problem: click_1() is called twice on first click, only once thereafter.
Solution: Add the click() handler but don’t call click_1().

	var click_1 = function($el) {
        //eliminar = $(this).attr('data-ruta')
        eliminar = $el.attr('data-ruta')
        $('#text-modal-competencia').html('')
        //id = $(this).attr('id')
        id = $el.attr('id')
        $.ajax({
            type:'post',
           ...
           ...
    }
    $('.btn-eliminar-competencia').click(function(){
		//click_1($(this));
	})
    $('#pjax-container').on('click', '.btn-eliminar-competencia', function(){
		click_1($(this));
	})

I guess the .on(‘element’, function() { …
will work if .click() with empty handler is added.
Obviously it will not without .click().

works!
you had told me somthing similar previously, but no have sucess.
Now works correctly
thanks a lot