Search code examples
grailsgroovygsp

How to keep query results after deleting an item?


In my Grails application I have multiple pages that list a group of data objects inside of a table. In these pages I provide a search function which when performed will adjust the table to only display the data objects that match the query. However If a user decides to delete one of these data objects the application will take them back to the default table which displays everything. I would like for query results to remain intact after performing a delete.

I will use my "Skill Evaluations" page as my example in this post.

Here is the relevant code in the domain class

SkillEval.groovy

class SkillEval {

    static hasMany = [lines: SkillEvalL, courses: CourseOffering, choiceLabels: ChoiceLabel]

    String name
    String formVersion


static def search(params) {
    def criteria = SkillEval.createCriteria()

    def results = criteria.list(params) {
        or {
            ilike("name", params.search+'%')
        }
    }

    return results
}
}

Relevant section of the gsp view file

list.gsp

    <g:form> 
        <div class="search">
            <label for="searchField">Search:</label> <input type="text"
                id="searchField" name="search" value="${params.search}" /> <input
                type="submit" value="Search" />
        </div>
        <br>

        <table id="mainTable">
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Version</th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>
                <g:each var="eval" in="${skillEvalList}">
                    <tr>
                        <td>
                            <strong>
                                ${eval.name}
                            </strong>
                        </td>
                        <td>
                            ${eval.formVersion}
                        </td>
                        <td>        
                            <g:actionSubmit value="Delete" controller="skillEval" action="delete" onclick="setId(${eval.id});return confirm('Are you sure?');" class="delete" />
                        </td>
                    </tr>
                </g:each>
            </tbody>
        </table>
        <g:if test="${(skillEvalCount/maxCount) > 1}">
            <div class="pagination">
                <g:paginate action="list" total="${skillEvalCount}" />
            </div>
        </g:if>

        <input id="evalId" type="hidden" name="id" value="" />
    </g:form>
</div>
<r:script>
    function setId(id)
    {
        $('#evalId').val(id);
    }
</r:script>

Relevant code in the Controller class

SkillEvalController.groovy

def delete(Long id) {

    def skillEval = SkillEval.get(id)

    if (skillEval) {
        def allInstances = SkillEvalI.findAllByForm(skillEval)

        allInstances.each { evalInstance ->
            evalInstance.lines.clear()
            if(!evalInstance.delete()) {
                println "Failed to delete skill eval instance"
            }
            else {
                println "Instance successfully deleted."
            }   
        }

        try {
            skillEval.delete(flush: true)

        }
        catch (DataIntegrityViolationException e) {

        }
    } 

    redirect(action: "list")
}


How can I make the view retain the queried results after deleting one of the queried items?


Solution

  • When you redirect to the list action you can provide parameters -- just capture the parameters (if any) in the delete action and pass them in the redirect call to list at the end of the controller action.

    (Update: Forgot that actionSubmit does not accept params as an attribute, so cobbled together this solution from this SO answer and the Grails docs)

    Example:

    // View (list.gsp)
    <g:actionSubmit action="deleteWithParams" value="Delete" ... />
    
    
    // Controller
    def list() {
        def deleteWithParams = { forward(action:'delete', params:[search: params?.search]) }
        render...
    }
    
    def delete(Long id) {
        // Deleting the skillEval ...
        redirect(action: "list", params: [search: params?.search])
    }