Render shows data for first cell encountered on all other cells

Render shows data for first cell encountered on all other cells

gcacgcac Posts: 21Questions: 1Answers: 0
edited November 2017 in DataTables 1.10

Using server-side.

I have a simple datatable where I check to see if some notes were entered in a field. If the field is not null, I want to display a warning icon that when clicked opens a modal with the content of that cell.

When I load the table the icons show correctly, ie. if there is data in the cell it shows the icon. However when I click the icon, it opens the modal correctly but only shows data from the first occurrence of something in the cell.

For example: 6 rows in the table. Rows 3 and 4 and 6 contain "admin_notes". When the table is rendered, rows 1 2 and 6 show correctly (ie no icon in that table cell), rows 3,4 and 5 show correctly (ie. show the button to denote admin_notes are present).

But when I click on the icon to open the modal for row 4, it shows the notes for row 3. Same for row 5. I've tried everything I can think of to fix. (disclaimer : not a JS expert at all).. Following are my column defs with the render.

        columns: [
            { data: "requests.name" },
            { data: "requests.department" },
            { data: "requests.preferred_system" },
            {
                "className":      'accessories',
                "orderable":      true,
                "searchable":     false,
                "data":           null,
                "defaultContent": ''
            },
            {
            // Want to add a click to open modal here  : Reference: https://datatables.net//forums/discussion/comment/22190/#Comment_22190
            data: "requests.admin_notes",
                    defaultContent: '',
                    render: function ( data, type, row ) {
                        if ( data != null && data != '') {
                            var notesModal = '<center><button type="button" class="btn btn-danger btn-circle" data-toggle="modal" data-target="#admNotesModal">'
                                +'<i class="fa fa-warning"></i></button></center>'
                                +'<div class="modal fade" id="admNotesModal" tabindex="-1" role="dialog" aria-labelledby="Admin Notes" aria-hidden="true">'
                                    +'<div class="modal-dialog">'
                                 +'<div class="modal-content">'
                                 +'<div class="modal-header">'
                                        +'<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>'
                                        +'<h4 class="modal-title" id="myModalLabel">Admin Notes</h4>'
                                    +'</div>'
                                    +'<div class="modal-body">'
                                    +data+'</div>';
                             return notesModal;
                            //return '<center><button type="button" class="btn btn-danger btn-circle" data-toggle="modal" data-target="#admNotesModal"><i class="fa fa-warning"></i></button></center>';
                        }
                     else {
                            return;
                        }
                    }
            },
            {
                "className":      'details-control',
                "orderable":      false,
                "searchable":     false,
                "data":           null,
                "defaultContent": ''
            },
            
            {
                data: null,
                sorting: false,
                
                className: "text-center",
                defaultContent: '<a href="" class="editor_edit"><button type="button" class="btn btn-primary btn-xs">Edit Application</button></a>'
            }
        ],

Replies

  • allanallan Posts: 63,531Questions: 1Answers: 10,475 Site admin

    I'm reasonably sure that its an issue with the id of the modal. If that code runs, you'll have multiple elements with the same id (id="admNotesModal") which is not valid HTML. The browser will "correct" that by simply selecting the first one, which is what you are seeing.

    One option would be to have a simple counter that gets incremented each time the renderer runs and use that in the id, so it is always unique.

    Another option would be to have the modal external to the renderer and have an event handler that populates it with the required content. Personally I prefer that option as I think it will make a smaller page.

    Allan

  • gcacgcac Posts: 21Questions: 1Answers: 0

    Allan, thanks for the quick reply.

    That makes perfect sense. You'll have to forgive me, I'm not as adept in JS as I'd like. Could you provide some reference links that I can research or examples? I think I can get it if you point me in the right direction.

    Thanks!
    Nate

  • gcacgcac Posts: 21Questions: 1Answers: 0

    I got it working, and I think I did the first way. I'd still like any guidance you can throw my way on the second method. Heres what I did:

    Outside of the main $(document).ready(function() { :

    var counter; counter = 0;
    

    Then in my colum definitions:

               {
                    data: "requests.admin_notes",
                    defaultContent: '',
                    render: function (  data, type, val, meta ) {
    
                        if ( data != null && data != '') {
                            counter++;
                            return '<center><button type="button" onclick="counter++" class="btn btn-danger btn-circle" data-toggle="modal" data-target="#admNotesModal'+counter+'">'
                            +'<i class="fa fa-warning"></i></button></center>'
                            +'<div class="modal fade" id="admNotesModal'+counter+'" tabindex="-1" role="dialog" aria-labelledby="Admin Notes" aria-hidden="true">'
                                +'<div class="modal-dialog">'
                             +'<div class="modal-content">'
                             +'<div class="modal-header">'
                                    +'<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>'
                                    +'<h4 class="modal-title" id="myModalLabel">Admin Notes</h4>'
                                +'</div>'
                                +'<div class="modal-body">'
                                +data+'</div>';
                        }
                        else {
                                return;
                        }
                    }
    

    It seems to work but like you said generates a larger page..

  • allanallan Posts: 63,531Questions: 1Answers: 10,475 Site admin

    Yup - that looks good for that method - nice one.

    So for the second method you would simply have the renderer return what you want to display in the table (i.e. the button). Remove the onclick DOM0 event handler and instead use something like:

    $('#myTable').on( 'click', 'button.btn', function () {
      var rowData = table.row( $(this).closest('tr') ).data();
    
      ...
    } };
    

    Then use rowData to write the data into an existing modal element and finally use the Bootstrap modal API to display the modal.

    Allan

This discussion has been closed.