Our Blog

Let us find tech solutions together

Feb 10

Wicket Ajax Confirmation Modal window

By kinabalu | Comments

 

(Editor’s note: Tomasz Dziurko contributed this column from Code Hard Go Pro.)

While developing web application with Wicket I sometimes need to check whether the user really, really does want to do something, for example to delete an entity from the database. The first and easiest choice that comes to my mind is to use JavaScript window. So we have HomePage.html:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
    <head>
        <title>Wicket Ajax 'Are you sure?' Modal Window</title>
    </head>
    <body>
        <div align="center">
            <strong>Wicket Ajax 'Are you sure?' Modal Window</strong>
            <form action="" wicket:id="formWithJavaScript">
                <input type="submit" wicket:id="buttonWithJavaScript" value="Action!"/>
            </form>
        </div>
    </body>
</html>

and corresponding Java class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package pl.tdziurko.ajaxmodalwindowapp;

// imports omitted

/**
 * Author: Tomasz Dziurko
 */

public class HomePage extends WebPage {

    private static final long serialVersionUID = 1L;

    public HomePage(final PageParameters parameters) {

        Form formWithJavaScript = new Form("formWithJavaScript");

        Button buttonWithJavaScript = new Button("buttonWithJavaScript") {

            @Override
            public void onSubmit() {
                System.out.println("Doing my job");
            }
        };
        buttonWithJavaScript.add(new SimpleAttributeModifier(
                "onclick", "if(!confirm('Do you really want to perform this action?')) return false;"));

        formWithJavaScript.add(buttonWithJavaScript);
        add(formWithJavaScript);

    }

}

Finally, we can see how it looks:

It solves our problem but in the era of Web2.0, rounded corners and shiny looks it isn’t enough. Why can’t we use ajax modal window to ask user for confirmation? It would make our application look good and our css magician could make it look even better.

So let’s try with creating reusable ‘Are you sure?’ ajax modal window with Wicket.

At the beginning we must prepare panel which will be displayed in our modal window. Let’s name it YesNoPanel.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:wicket>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <title></title>
    </head>
    <body>
        <wicket:panel>
            <form wicket:id="yesNoForm" action="">
                <span wicket:id="message">Are you sure?</span>
                <table style="width: 65%;" align="center">
                    <tr>
                        <td align="left">
                            <input type="submit" wicket:id="noButton" value="No" />
                        </td>
                        <td align="right">
                            <input type="submit" wicket:id="yesButton" value="Yes" />
                        </td>
                    </tr>
                </table>
            </form>
        </wicket:panel>
    </body>
</html>

and Java class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package pl.tdziurko.ajaxmodalwindowapp.areyousuremodal;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.basic.MultiLineLabel;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.Panel;
import pl.tdziurko.ajaxmodalwindowapp.areyousuremodal.AreYouSurePanel.ConfirmationAnswer;

public class YesNoPanel extends Panel {

    public YesNoPanel(String id, String message, final ModalWindow modalWindow, final ConfirmationAnswer answer) {
        super(id);

        Form yesNoForm = new Form("yesNoForm");

        MultiLineLabel messageLabel = new MultiLineLabel("message", message);
        yesNoForm.add(messageLabel);
        modalWindow.setTitle("Please confirm");
        modalWindow.setInitialHeight(200);
        modalWindow.setInitialWidth(350);

        AjaxButton yesButton = new AjaxButton("yesButton", yesNoForm) {

            @Override
            protected void onSubmit(AjaxRequestTarget target, Form form) {
                if (target != null) {
                    answer.setAnswer(true);
                    modalWindow.close(target);
                }
            }
        };

        AjaxButton noButton = new AjaxButton("noButton", yesNoForm) {

            @Override
            protected void onSubmit(AjaxRequestTarget target, Form form) {
                if (target != null) {
                    answer.setAnswer(false);
                    modalWindow.close(target);
                }
            }
        };

        yesNoForm.add(yesButton);
        yesNoForm.add(noButton);

        add(yesNoForm);
    }

}

Everything looks pretty straightforward. We pass to the constructor text which will be displayed as a confirmation question, references to ModalWindow object in which YesNoPanel is placed and to ConfirmationAnswer object. ConfirmationAnswer class will be created in the next paragraph and will be used to store information whether user pressed ‘Yes’ or ‘No’ button in our panel.

Now it’s time to prepare wrapping form to our YesNoPanel. We could simply achieve it by creating panel with form and one button in it. In our example it will be AreYouSurePanel class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:wicket>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <title></title>
    </head>
    <body>
        <wicket:panel >
            <form wicket:id="confirmForm" action="" style="display: inline;">
                <input type="submit" wicket:id="confirmButton" value="Default name" />
                <span style="display: none;" wicket:id="modal"></span>
            </form>
        </wicket:panel>
    </body>
</html>

and in Java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package pl.tdziurko.ajaxmodalwindowapp.areyousuremodal;

import java.io.Serializable;
import java.util.Map;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;


public abstract class AreYouSurePanel extends Panel {

    protected ModalWindow confirmModal;
    protected ConfirmationAnswer answer;
    protected Map<string,string> modifiersToApply;


    public AreYouSurePanel(String id, String buttonName, String modalMessageText) {
        super(id);
        answer = new ConfirmationAnswer(false);
        addElements(id, buttonName, modalMessageText);
    }

    protected void addElements(String id, String buttonName, String modalMessageText) {

        confirmModal = createConfirmModal(id, modalMessageText);

        Form form = new Form("confirmForm");
        add(form);

        AjaxButton confirmButton = new AjaxButton("confirmButton", new Model(buttonName)) {

            @Override
            protected void onSubmit(AjaxRequestTarget target, Form form) {
                confirmModal.show(target);
            }
        };

        form.add(confirmButton);


        form.add(confirmModal);

    }

    protected abstract void onConfirm(AjaxRequestTarget target);
    protected abstract void onCancel(AjaxRequestTarget target);

    protected ModalWindow createConfirmModal(String id, String modalMessageText) {

        ModalWindow modalWindow = new ModalWindow("modal");
        modalWindow.setCookieName(id);
        modalWindow.setContent(new YesNoPanel(modalWindow.getContentId(), modalMessageText, modalWindow, answer));
        modalWindow.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {

            @Override
            public void onClose(AjaxRequestTarget target) {
                if (answer.isAnswer()) {
                    onConfirm(target);
                } else {
                    onCancel(target);
                }
            }
        });

        return modalWindow;
    }

    public class ConfirmationAnswer implements Serializable {

        private boolean answer;

        public ConfirmationAnswer(boolean answer) {
            this.answer = answer;
        }

        public boolean isAnswer() {
            return answer;
        }

        public void setAnswer(boolean answer) {
            this.answer = answer;
        }
    }

}

Here we do following steps:

  1. Create form with one AjaxButton which shows modalWindow when clicked.
  2. Create modalWindow with YesNoPanel in it. As mentioned earlier, we pass there references to our modal window and to confirmationAnswer object.
  3. Add WindowClosedCallback to modalWindow and basing on user choice perform onConfirm or onCancel method. These methods are both abstract to force developer extending AreYouSurePanel to implement them according to his needs.

That’s it, we are done. To test how it’s working we must change a bit our page class and html file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
    <head>
        <title>Wicket Ajax 'Are you sure?' Modal Window</title>
    </head>
    <body>




        <div align="center">
            <strong>Wicket Ajax 'Are you sure?' Modal Window</strong>




            <form action="" wicket:id="formWithJavaScript">
                <input type="submit" wicket:id="buttonWithJavaScript" value="Action!"/>
            </form>
        </div>



        <div align="center">
            <span wicket:id="yesNoPanel"/>
        </div>

    </body>
</html>

and

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package pl.tdziurko.ajaxmodalwindowapp;

// imports omitted

public class HomePage extends WebPage {

    private static final long serialVersionUID = 1L;

    public HomePage(final PageParameters parameters) {

        Form formWithJavaScript = new Form("formWithJavaScript");

        Button buttonWithJavaScript = new Button("buttonWithJavaScript") {

            @Override
            public void onSubmit() {
                System.out.println("Doing my job");
            }
        };
        buttonWithJavaScript.add(new SimpleAttributeModifier(
                "onclick", "if(!confirm('Do you really want to perform this action?')) return false;"));

        formWithJavaScript.add(buttonWithJavaScript);
        add(formWithJavaScript);

        AreYouSurePanel yesNoPanel = new AreYouSurePanel("yesNoPanel", "Ajax Action!", "Do you really want to perform this action?") {

            @Override
            protected void onConfirm(AjaxRequestTarget target) {
                System.out.println("Doing my job after ajax modal");
            }

            @Override
            protected void onCancel(AjaxRequestTarget target) { }

        };

        add(yesNoPanel);
    }

}

And after clicking ‘Ajax Action!’ we could see that it’s working as intended: