Search code examples
javascriptjquerygrailsgsp

Grails gsp wait for data to display in divs


i try to build a gsp with Grails 3 that displays some Database statistics. Some of the Statistics take a moment to be generated. I want to display a placeholder "Please wait" in the divs the statistics should appear. After the data is available those placeholders should be replaced this the actual data.

I want the rest of the page to be rendert so the user dosn't think the page is not responding.

I tried something like this to test the function in the Controller:

def addMe = {
    sleep(5000)
    render {
        div(id: "bla", "some text inside the div")
    }
}

And this inside the gsp:

<g:include action="addMe" />

But the page waits for the function to finish until the end is loaded. How to skip the waiting?


Solution

  • The following should be enough to give you a rough idea how to implement.

    After clicking the button a javascript function is called which fetches the data from the DbStatsController getStats function.

    You should see the spinner icon displayed while the work is being done which is hidden by default & shown/hidden by the showSpinner function.

    Errors will be shown in the div with id resultDiv as will the results from your action which for the demo are being returned a JSON.

    dbStats\index

    <!DOCTYPE html>
    <html>
    <head>
        <meta name="layout" content="main" />
    
        <script type="text/javascript">
            function showSpinner(visible) {
                if (visible) $('#spinner').show();
                else $('#spinner').hide();
            }
    
            $(document).ready(function(){
                $( '#dbStats' ).click( function() {
                    $.ajax( {
                        url: "${g.createLink( controller: 'dbStats', action: 'getStats')}",
                        type: "get",
                        timeout: 5000,
                        success: function ( data ) {
                            $( '#resultDiv' ).html( data )
                        },
                        error: function(jqXHR, textStatus, errorThrown) {
                            $( "#resultDiv" ).addClass( 'alert alert-danger' ).text( 'Unable to get stats ' + errorThrown )
                        },
                        beforeSend: function() { showSpinner( true ) },
                        complete: function() { showSpinner( false ) }
                    } );
                })
            });
        </script>
    </head>
    <body>
    
    <asset:image src="spinner.gif" id="spinner" style="display: none" />
    
    <div id="resultDiv"></div>
    
    <g:form>
        <button type='button' id="dbStats">Get DB stats</button>
    </g:form>
    
    </body>
    

    DbStatsController

    import grails.converters.JSON
    
    class DbStatsController {
    
        def index() { }
    
        def getStats() {
            render ( [stat1: 123, stat2: 321] ) as JSON
        }
    }