Lorenzo Lorenzo - 2 months ago 21
jQuery Question

Grails - Close bootstrap modal after AJAX call

Im working on a login page using

Grails
<formRemote>
tag and
Bootstrap Modal

Everything works except I don't know how to close de modal after login success.

with:


$('#myModal').modal('hide')


On login fail I update #modal-body with the errorMessage returned by my controller (LoginController) and that is fine but when login success (ajaxSuccess method in LoginController) I redirect to the home page and I don't know how to tell the modal to close at this time.

Some help would be very appreciated.

Here is the form template snippet that send the AJAX Call.


<g:formRemote url="[controller:'j_spring_security_check', action:'']"
name="loginForm"
update="modal-body"
class="form-inline"
on401="alert('error');">
<input type="text" name="j_username" class="input" placeholder="email" autocomplete="on" value="" id="j_username">
<input type="password" name="j_password" class="input" placeholder="password" value="" id="j_password">
<input id="loginButton" type="submit" value="Login" class="btn"
data-trigger="manual" data-toggle="popover" data-placement="bottom" data-html="true" data-content="<span></span>" />
<div class="login-message" id="login-message">${message}</div>
</g:formRemote>

<script>
<g:if test="${message == 'success'}">
$(function() {
$('#myModal').modal('hide');
});
</g:if>
</script>


Here is the Bootstrap Modal snippet that render the loginForm template inside #modal-body

<div id="cont">
<div class="modal fade hide" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" data-remote="">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Login/Register</h3>
</div>
<div id="modal-body" class="modal-body">
<g:render template="/login/templates/loginForm"></g:render>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
</div>
</div>
</div>


And this is authfail and ajaxSuccess method from the LoginController


def authfail = {
def username = session[UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY]
String errorMessage = ''
def exception = session[WebAttributes.AUTHENTICATION_EXCEPTION]

if (exception) {
if (exception instanceof AccountExpiredException) {
errorMessage = g.message(code: "springSecurity.errors.login.expired")
}
else if (exception instanceof CredentialsExpiredException) {
errorMessage = g.message(code: "springSecurity.errors.login.passwordExpired")
}
else if (exception instanceof DisabledException) {
errorMessage = g.message(code: "springSecurity.errors.login.disabled")
}
else if (exception instanceof LockedException) {
errorMessage = g.message(code: "springSecurity.errors.login.locked")
}
else {
errorMessage = g.message(code: "springSecurity.errors.login.fail")
}
}
if (springSecurityService.isAjax(request)) {
render(template: '/login/templates/loginForm', model: [message:errorMessage])
//render(errorMessage)
}
else {
render view: '/index' , params: params
//redirect action: 'auth', params: params
//render([error: msg] as JSON)
}
}


This is the ajaxsuccess method


def ajaxSuccess = {
render(template: '/login/templates/loginForm', model: [message:"success"])
}


I keep the commented line so you can see what I tried to do.

Thank in advance

Answer

if your gsp looks somehow like this :

<div id="modal-body">
   <g:render template="/login/templates/loginForm" model="[errorMessage:'none']" />
</div>

<g:formRemote ....

you could simply add some javascript to your template, it will run when the Dom is completely updated with ajax response and make sure the errorMessage variable is set initialy like above to "none"

    <div id="cont">
        <div class="modal fade hide" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" data-remote="">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
                <h3 id="myModalLabel">Login/Register</h3>
            </div>
            <div id="modal-body" class="modal-body">
                <g:render template="/login/templates/loginForm"></g:render>
            </div>
            <div class="modal-footer">
                <button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
            </div>
        </div>
    </div>
    <script>
        <g:if test="${errorMessage == 'success'}">
            // it will only close if the errorMessage from ajax is 'success, wich by the way is not an error ^^
            $(function() {
                $('#myModal').modal('hide');
            });
        </g:if>
    </script>