Charles
Charles

Reputation: 148

Prevent a modal from closing

This is I want to do:

I have a few successes, but not with 2.2, id est, keep the modal open when error is sent back.

This is the code I have so far:

<div class="ui modal" id="createAddress">
    <i class="close icon"></i>
    <div class="header">
        Adresses
    </div>
    <div class="content">
        <div class="ui form">
            <?php
            $encrypter = app('Illuminate\Encryption\Encrypter');
            $encrypted_token = $encrypter->encrypt(csrf_token());
            ?>
            <input id="token" type="hidden" value="{{$encrypted_token}}">
            <div class="field">
                <label>Address</label>
                <input type="text" id="address">
            </div>
            <div class="two fields">
                <div class="field">
                    <label>Zip</label>
                    <input type="text" id="zip">
                </div>
                <div class="field">
                    <label>County</label>
                    <input type="text" id="county">
                </div>
            </div>
            <div class="field">
                <label>Country</label>
                <input type="text" id="country">
            </div>
            <div class="field">
                <label>Phone</label>
                <input type="text" id="phone">
            </div>
            <div class="field">
                <label>E-mail</label>
                <input type="text" id="email">
            </div>
        </div>
    </div>
    <div class="actions">
        <div class="ui red cancel button">Cancel</div>
        <div class="ui positive button">Save</div>
    </div>
</div>

$('.ui.modal')
        .modal({
            onApprove : function() {
                var $_token = $('#token').val();
                var dataJs = {  address:$("#address").val(),
                                zip:$("#zip").val(),
                                county:$("#county").val(),
                                country:$("#country").val(),
                                tel:$("#tel").val(),
                                email:$("#email").val()};
                $.ajax({
                    type: 'POST',
                    headers: { 'X-XSRF-TOKEN' : $_token },
                    dataType: 'json',
                    data: dataJs,
                    url: '/admin/relationshipTmpAddressesStoreAjax',
                    error: function(xhr, textstatus, errorThrown){
                        alert('request failed');
                        return false
                    }
                });
            }
        })
        .modal('show')

Upvotes: 4

Views: 9043

Answers (3)

Troy Niemeier
Troy Niemeier

Reputation: 140

I agree with @MTran, except the last part where that answer begins considering synchronous requests. There's a better way! :)

Firstly, variablize your modal element. let $createAddressModal = $('#createAddress');

Then, in the onApprove handler, return false; at the end no matter what, because you want to hide the modal conditionally, later (not now, when the onApprove handler needs to complete execution) Later, in the response handler functions, you can conditionally 'hide' the modal as/when necessary by referring back to your modal variable (D.R.Y. by reselecting the modal).

$createAddressModal.modal({
    // settings...,
    onApprove: function() {
        
        let ajaxRequest = $.ajax({ ... });

        ajaxRequest.done(function(response) {

            if(response.is42) {
                $createAddressModal.modal('hide'); // <-----
            }
        });

        ajaxRequest.fail(function(x, y, z) { ... });

        return false;
    }
});

Upvotes: 0

MTran
MTran

Reputation: 1809

I have success with what your trying to do. I basically had to "return false" for onApprove property so that semantic UI doesn't close my modal on button click for the approve(save) button.

Your "return false" for ajax function hasn't reached to semantic UI's onApprove property, it just returns false for that anonymous function, leaving onApprove without a return value, and so the result is closing the modal on approve(save) button click.

So something similar to:

$('.ui.modal').modal({
  onApprove : function() {
    ... //Validate here, or pass validation to somewhere else
    return false; //Return false as to not close modal dialog
  }
}).modal('show');

Here's how I did it, but I used semantic UI form validations instead of JQuery Validations and AJAX: http://plnkr.co/edit/5fK7UuJIm7QTJGiu23NL?p=preview

Also recall AJAX is asynchronous, so your AJAX request would be sent, and your code will continue execute the rest of the onApprove function without a response from the AJAX code.

Perhaps these steps should be taken if you need to stick with AJAX and JQuery validations:

  1. Take a look at synchronous AJAX, from How can I get jQuery to perform a synchronous, rather than asynchronous, Ajax request?
  2. You need to figure out how to get the return value of that AJAX request
  3. Return that value as the onApprove function's return value.

Upvotes: 6

Charles
Charles

Reputation: 148

thanks for that Oniisaki. I had progressed and came to the path you suggested in your answer.

This is the code I came up with (I'm actually using a variable to define the return value):

        $('.ui.modal')
                .modal({
                    selector    : {
                        close    : '.close, .actions .button',
                        approve  : '.actions .positive, .actions .approve, .actions .ok',
                        deny     : '.actions .negative, .actions .deny, .actions .cancel'
                    },

                    onShow: function(){
                        $("#createAddressForm .field")
                                .removeClass("error");
                        $("#createAddressForm .field :input")
                                .attr("placeholder", "")
                                .val("")
                    },

                    onApprove: function () {

                        var $_token = $('#token').val();
                        var dataJs = {
                            address: $("#address").val(),
                            zip: $("#zip").val(),
                            county: $("#county").val(),
                            country: $("#country").val(),
                            tel: $("#tel").val(),
                            email: $("#email").val()
                        };

                        $.ajax({
                            type: 'POST',
                            async: false,
                            headers: {'X-XSRF-TOKEN': $_token},
                            dataType: 'json',
                            data: dataJs,
                            url: '/admin/relationshipTmpAddressesStoreAjax',

                            success: function(){
                                ajaxSucceeded = true;
                                console.log('did it')
                            },

                            error: function (xhr, textstatus, errorThrown) {
                                ajaxSucceeded = false;
                                $.each(JSON.parse(xhr.responseText), function (index, element) {
                                    $('#' + index)
                                            .attr("placeholder", element)
                                            .parent().addClass("error")

                                });
                            }
                        });

                        return ajaxSucceeded;

                    }
                })
                .modal('show')
    } );

At first, I used the code without changing the async default and indeed, as you suggest in your answer, I had to set it to false to make sure that I got a return value from the ajax-call before arriving to the end of the onApprove closure.

The onShow part makes the code more complete. If I hadn't put it there, the fields would still be in error state when the modal would show up again after hitting the cancel button after an error save.

Upvotes: 0

Related Questions