1

I have a gsp page with a delete button for each row of a table. On the button click I want a pop up which tells the consequences of the delete. These consequences depends on the data present in the row and a few other constraints known to the grails service which is called from the grails controller associated to the gsp page. If the user confirms these consequences the row should be deleted from the table, else the table remains unchanged.

How should i go about to achieve this behavior?

Currently, I have in my gsp

<tr>
    <td>name</td>
    <td>parentName</td>
    <td>data</td>
    <td>
        <g:link action="deleteRow" params="${[name: row.name, parentName: row.parentName]}">
            <button class="deleteSnapshot">Delete</button>
        </g:link>
    </td>
</tr>

and in my .js file

$(document).on('click', ':button', function (e) {
        var btn = $(e.target);
        btn.attr("disabled", "disabled"); // disable button
        alert('getting deletion details');
        //var deletionDetails -->not sure how to get these
        //var deletionDetails will get data from controller action:"getDetails"
        if (confirm('/*print deletion details and ask*/ Do you want to proceed?')) {
            alert('will delete')
            return true
        }
        else {
            btn.removeAttr("disabled"); // enable button
            return false
        }
    });

and in my controller

class DeleteController{
    DeleteService deleteService
    def index() {
        [list:deleteService.getTableList()]
    }
    def getDeletionDetails(string name, String parentName){
        return deleteService.getDetails(name,parentName)
    }
    def deleteRow(String name, String parentName){
        service.deleteRow(name, parentName)
        redirect controller:"DeleteController", action:"index"
    }
}

I know the deletion works fine, because it works even with in the current state. Just that the confirmation box asks Do you want to proceed, without displaying the details.

Any help on how i could achieve what I am looking for will be appreciated.

P.S. I am new to stackoverflow, so if i missed out on certain convention do let me know.

Thanks in advance.

1 Answers1

1

I can think of two ways of doing it:

The first one is using ajax to both get deletion details and delete the row

Assuming that deleteService.getDetails(name, parentName) returns a String, first you need to change an getDeletionDetails action so it renders the response:

def getDeletionDetails(String name, String parentName){
    render deleteService.getDetails(name, parentName)
}

and change g:link-s to buttons in gsp:

<button data-name="${row.name}" data-parent-name="${row.parentName}">
     Delete
</button>

In your .js then put:

$(document).on('click', ':button', function (e) {
    var btn = $(e.target);

    btn.attr("disabled", "disabled"); // disable button

    var name = btn.data('name');
    var parentName = btn.data('parentName');

    $.ajax({
        url: "/delete/getDeletionDetails",
        data: {
            name: name,
            parentName: parentName
        },
        success: function (data) {
            if (confirm(data + '\nDo you want to proceed?')) {
                $.ajax({
                    url: '/delete/deleteRow',
                    data: {
                        name: name,
                        parentName: parentName
                    },
                    success: function (d) {
                        console.log("Success: " + d);
                    }
                });
            } else {
                btn.removeAttr("disabled"); // enable button
            }
        }
    });
});

What this code does is it sends an ajax call to /delete/getDeletionDetails, then uses its response (rendered by getDeletionDetails action in DeleteController) to show a confirmation alert. If user confirms the question, another ajax call is sent - now to deleteRow action of DeleteController - with parameters taken from data attributes of clicked button. If user cancels - nothing happens, except for reenabling a button.

Your deleteRow should only change the return statement - it also must render the response:

def deleteRow(String name, String parentName){
    service.deleteRow(name, parentName)
    render "You deleted an item $name - $parentName."
}

You don't need redirect here, because - thanks to using ajax - user will never leave delete/index. You can just display some kind of confirmation on page after successful ajax call.

The second option is to put deletion details in hidden fields or data- attributes in each row and then just retrieve them in js:

You can create a method getDeletionDetails() in row's domain class (presumably Row) that returns the details (using services in domain classes is not perfect, but is should work ok if the service is not very complex). Then, in your .gsp place:

<td>
    <g:link action="deleteRow" params="${[name: row.name, parentName: row.parentName]}">
        <button class="deleteSnapshot" data-details="${row.deletionDetails}">Delete</button>
    </g:link>
</td>

You should then be able to get details in .js like this:

var deletionDetails = btn.data('details');
Community
  • 1
  • 1
pawels
  • 1,070
  • 1
  • 10
  • 16
  • Thanks @suricatta. This is amazing. It worked exactly the way i needed it to. I just had a doubt and a question. 1. Why does "data-parent-name="${row.parentName}" work and "data-parentName="${row.parentName}" not work in my gsp page? 2. After the delete, the row is deleted from the database but not from the page. I need to refresh the page for the like to disappear. Is this because we removed the redirect? Once again, thanks a lot, not only for the solution but actually typing the whole code down here with detailed explanation. It is very helpful for a noob like me. :-) – Vaibhav Karani Oct 09 '17 at 18:15
  • Also, I used solution 1, even though I tried both the solutions and they worked just fine. – Vaibhav Karani Oct 09 '17 at 18:23
  • @VaibhavKarani Ad. 1. I'm afraid I don't have enough information to answer this question. What do you mean by "not work in my gsp page"? Ad. 2. Yes - the view doesn't change because everything is done by ajax - you can remove the row manually in the _success_ callback of the ajax call using jQuery (find the _tr_ and _.remove()_ it, it shouldn't be difficult). – pawels Oct 09 '17 at 20:00
  • What i meant was that when i use the solution mentioned by you, it works fine and the name and the parentName are received correctly. However, when i use data-parentName="${row.parentName}" instead of data-parent-name="${row.parentName} in my gsp page, the value captured by the .js is null. Why is the working so? – Vaibhav Karani Oct 09 '17 at 23:05
  • @VaibhavKarani I think now data attributes should be lowercase: https://stackoverflow.com/a/22753630/2224598, so maybe using `.data('parentname')` will work. Also, if the solution worked, would you mind accepting the answer? – pawels Oct 10 '17 at 06:14
  • Thanks @suricatta for the help. I have accepted the solution. Could you too please upvote the question. :-) – Vaibhav Karani Oct 12 '17 at 01:31
  • Sure, @VaibhavKarani, it was well written question. – pawels Oct 12 '17 at 06:25