0

I making a simple CRUD web application using spring boot(1.5.2.RELEASE) + thymeleaf(2.1.5) + datatables(1.10.13) + jQuery(3.1.1) + Bootstrap(3.3.7). Everything works fine, but the problem is to make it display links correctly after adding new row from form. (table_view_issue) And after I reload the page - it's OK. So, this is my table:

<table id="table_users" class="display" cellspacing="0" width="100%">
                <thead>
                <tr>
                    <th class="text-center">NAME</th>
                    <th class="text-center">AGE</th>
                    <th class="text-center">ADDRESS</th>
                    <th class="text-center">DELETE</th>
                    <th class="text-center">EDIT</th>
                </tr>
                </thead>
                <tbody>
                <tr class="text-center" th:each="user : ${users}">
                    <td th:text="${user.name}"></td>
                    <td th:text="${user.age}"></td>
                    <td th:text="${user.address}"></td>
                    <td><a th:href="'/delete/' + ${user.id}">Delete</a></td>
                    <td><a th:href="'/edit/' + ${user.id}">Edit</a></td>
                </tr>
                </tbody>
            </table>

form for adding:

    <form id="userForm" class="form-horizontal">
        <div class="form-group">
            <label class="col-sm-4 control-label" for="name">Name: </label>
            <div class="col-sm-4">
                <input class="form-control" id="name" name="name" type="text" th:minlength="1" th:maxlength="15"
                       th:required="required"/>
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-4 control-label" for="age">Age: </label>
            <div class="col-sm-4">
                <input class="form-control" id="age" name="age" type="number" th:min="1" th:max="130"
                       th:required="required"/>
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-4 control-label" for="address">Address: </label>
            <div class="col-sm-4">
                <input class="form-control" id="address" name="address" type="text" th:minlength="5"
                       th:required="required"/>
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-offset-4 col-sm-10">
                <input class="btn btn-success" type="submit" value="Add"/>
                <input class="btn btn-warning" type="reset" value="Reset"/>
            </div>
        </div>
    </form>

script for datatables:

$(document).ready(function () {
    $('#table_users').DataTable({
        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
    });
});

script to add user:

<script type="text/javascript">
        $(document).ready(function () {
            $("#userForm").submit(function (event) {
                // Prevent the form from submitting via the browser.
                event.preventDefault();
                ajaxPost();
            });


            function ajaxPost() {

                // PREPARE FORM DATA
                var formData = {
                    name: $("#name").val(),
                    age: $("#age").val(),
                    address: $("#address").val()
                };

                // DO POST
                $.ajax({
                    type: "post",
                    contentType: "application/json",
                    url: "/add",
                    data: JSON.stringify(formData),
                    dataType: 'json',
                    success: addData()
                });

                function addData() {
                    var deleteCell = '<td><a>Delete</a></td>';
                    var editCell = '<td><a>Edit</a></td>';

                    var rowAdded = $('#table_users').DataTable()
                        .row.add(
                        [
                            formData.name,
                            formData.age,
                            formData.address,
                            $(deleteCell).find('a').attr('href', '/delete/${user.id}'),
                            $(editCell).find('a').attr('href', '/edit/${user.id}')
                        ]
                    ).draw(false).node();

                    $(rowAdded).addClass('text-center');
                }


                // Reset FormData after Posting
                resetData();

            }

            function resetData() {
                $("#name").val("");
                $("#age").val("");
                $("#address").val("");
            }
        });
    </script>

Is it possible to do that without reloading? Thanks!

horbatiuk88
  • 3
  • 1
  • 2
  • Can you debug that object and tell us what's in it? Btw, solution is pretty overcomplicated. It could be done easier. – Branislav Lazic Mar 30 '17 at 14:40
  • I read here [link](http://stackoverflow.com/questions/4750225/what-does-object-object-mean) and here [link](http://stackoverflow.com/questions/8892465/javascript-object-object-means), and understood, that it was happening, because I was trying to add jQuery object to the table cell, and page must be reloaded to parse it. – horbatiuk88 Mar 30 '17 at 19:56
  • Actually, I was wrong about parsing and reloading .... because after reload table fills from controller and it doesn't matter what was there. – horbatiuk88 Mar 30 '17 at 20:25

1 Answers1

0

Problem 1 - Displaying the link in the table

I think that the problem is caused by the following two lines:

$(deleteCell).find('a').attr('href', '/delete/${user.id}'),
$(editCell).find('a').attr('href', '/edit/${user.id}')

You are not adding the deleteCell and the editCell but the return value of attr... According to the jQuery doc the return value is a jQuery reference. We can fix this by binding the url first and insert the element afterwards:

function addData() {
    var deleteCell = $('<td><a>Delete</a></td>');
    var editCell = $('<td><a>Edit</a></td>');
    // bind href first and insert the cells later
    deleteCell.find('a').attr('href', '/delete/${user.id}'),
    editCell.find('a').attr('href', '/edit/${user.id}')
    var rowAdded = $('#table_users').DataTable()
        .row.add(
        [
            formData.name,
            formData.age,
            formData.address,
            deleteCell,
            editCell
        ]
    ).draw(false).node();
}

Problem 2 - Actually generating the correct link...

I don't think that ${user.id} will be resolved to the actually userId in your Javascript. Thymeleaf can also be used for parsing javascript. However I don't think that it should be used like that in your case as you are using ajax requests any way.

There are some disadvantages when generating the new table row by using the form data:

  • if the server changes the format of the input (e.g. removing trailing whitespace) the user would still see the old format of the text as your table gathers the information from the form itself.

  • form validation (e.g. displaying error messages if the input was wrong). You could of course just validate the input on the client side. However be warned! Validating on the client side WONT stop bad requests from happening as we are not forced to use your from to submit data to your server.

That's why I'd suggest sending the validated data back to your client as an answer to your ajax request. The validated data can now also include your userId. This is a little more complex so i will only go into details if you want.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Tommy Schmidt
  • 1,224
  • 1
  • 16
  • 30
  • Problem 1) I did it as you adviced me, but now it refers to empty 'Edit' link (Edit). After I tried **var editRow = 'Edit'**; and it refers to **Edit**, but when I move coursor on Edit link, it shows me **/edit/$%7Buser.id%7D** and of course my controller won't understand this 'abrakadabra' as PathVariable Long Id :) – horbatiuk88 Mar 30 '17 at 21:10
  • Problem 2) Yes, you were right. And now I have enought arguments to say that it is wrong way to implement my idea. Perhaps, I need to read/watch more tutorials/manuals about jQuery and ajax to make it right with **correct** server side validation(e.g hibernate validator). Thanks a lot for your instructions, I really appreciate it. – horbatiuk88 Mar 30 '17 at 21:36