locked
datatables.net with bootstrap dropdrown to launch modal RRS feed

  • Question

  • User1503570896 posted

    Hi there,

    I wasn't sure which forum section I should post this one in. So if it belongs somewhere else I can move it over!

    I want to populate a datatables.net table with data (done), create my CRUD buttons in the last column (done) on click I want them to launch a modal with the relevant PartialView displayed.

    I had my modal buttons working before putting them into the datatables, I thought I could transpose the working code, however, that's not the case. I'm not even sure that I'm even close now and Google isn't getting me what I need (or I'm searching for the wrong things!)

    I suspect the problem lays in how I'm building the URLs. I'm using Areas in my project.

    Index.cshtml

    @model IEnumerable<Property>

    @{
    ViewBag.Title = "Properties";
    ViewBag.Subtitle = "The backbone of your business";
    }

    <div id="ModalPlaceHolder"></div>

    <div class="row justify-content-start">
    <div class="col-xxl-6 col-xl-8">
    <div class="card">
    <div class="card-body">
    <div class="row mb-5">
    <div class="col-md-12">
    <a asp-action="Create" class="btn btn-primary float-right">New Brand</a>
    </div>
    </div>
    <div class="datatable">

    <table id="tblData" class="table" style="100%">
    <thead>
    <tr>
    <th>Id</th>
    <th>Brand Name</th>
    <th>Property Name</th>
    <th>Short Description</th>
    <th>Status</th>
    <th></th>
    </tr>
    </thead>
    </table>

    </div>
    </div>
    </div>
    </div>
    </div>

    @section Styles{
    <link rel="stylesheet" href="~/lib/datatables/css/dataTables.bootstrap4.min.css" asp-append-version="true" />
    }

    @section Scripts{
    <script src="~/lib/datatables/js/jquery.dataTables.min.js" asp-append-version="true"></script>
    <script src="~/lib/datatables/js/dataTables.bootstrap4.js" asp-append-version="true"></script>

    <script src="~/js/backend/properties.js" asp-append-version="true"></script>
    }

    properties.js

    var dataTable;

    $(document).ready(function () {
    loadDataTable();
    });

    function loadDataTable() {
    dataTable = $('#tblData').DataTable({
    "ajax": {
    "url": "LoadData",
    "dataSrc": '',
    "type": "GET",
    "datatype": "json"
    },
    "columns": [
    { "data": "id" },
    { "data": "brand.brandName" },
    { "data": "propertyName" },
    { "data": "shortDescription" },
    { "data": "propertyStatus.status" },
    {
    "data": "id",
    "render": function (data) {
    return `<div class="btn-group">
    <button type="button" class="btn btn-primary btn-sm dropdown-toggle rounded-0" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Actions
    </button>
    <div class="dropdown-menu rounded-0">
    <a class="dropdown-item" data-toggle="ajax-modal" data-target="#DetailsProperty" data-url="@Url.Action("Details", "Property", new { Area = "Hosts" , Id = ${data} } )">Details</a>
    <a class="dropdown-item" data-toggle="ajax-modal" data-target="#EditProperty" data-url="@Url.Action("Edit", "Property", new { Area = "Hosts" , Id = ${data} )">Edit</a>
    <a class="dropdown-item" data-toggle="ajax-modal" data-target="#DeleteProperty" data-url="@Url.Action("Delete", "Property", new { Area = "Hosts" , Id = ${data} } )">Delete</a>
    </div>
    </div>`;
    }
    }
    ],
    "columnDefs": [
    {
    "targets": [0],
    "visible": false,
    "searchable": false
    }
    ]
    });
    }

    modal.js


    $(function () {

    var ModalPlaceHolderElement = $('#ModalPlaceHolder');

    $('button[data-toggle="ajax-modal"]').click(function (event) {

    var url = $(this).data('url');
    var decodedUrl = decodeURIComponent(url);
    $.get(decodedUrl).done(function (data) {
    ModalPlaceHolderElement.html(data);
    ModalPlaceHolderElement.find('.modal').modal('show');
    })
    })

    ModalPlaceHolderElement.on('click', '[data-save="modal"]', function (event) {
    event.preventDefault();
    var form = $(this).parents('.modal').find('form');
    var actionUrl = form.attr('action');
    var sendData = form.serialize();
    $.post(actionUrl, sendData).done(function (data) {
    ModalPlaceHolderElement.find('.modal').modal('hide');
    })
    })

    });

    Saturday, August 22, 2020 6:38 PM

All replies

  • User-1330468790 posted

    Hi Fresh Sight,

     

    There are two errors in your codes:

    1. You should not use "@Url.Action("Edit", "Property", new { Area = "Hosts" , Id = ${data} )" in Javascript file. It is a helper method which is written in C#, not javascript. It will directly render a link with value "id=1" like "@Url.Action("Edit", "Property", new { Area = "Hosts" , Id =1 )". However, I think what you expect should be "/Hosts/Property/Edit/1".  That means, you should use "/Hosts/Property/Edit/${data}".
    2. You should not call the modal related function immediately after the document loaded. At that time, the datatable does not complete the ajax call. Therefore, the modal event handler cannot be added successfully.

     

    More details, you could refer to below codes: (I only implement for the action "Details" ).

    HomeController: (In area "Hosts")

    [Area("Hosts")]
        public class HomeController : Controller
        {
            public IActionResult Index()
            {
                return View();
            }
    
    
            public IActionResult LoadData()
            {
                List<Property> list = new List<Property>
                {
                    new Property
                    {
                         id = 1,
                         brand= new Brand
                         {
                             brandName = "Brand1"
                         },
                         propertyName="Property Name 1",
                         propertyStatus = new PropertyStatus
                         {
                             status="Normal"
                         },
                        shortDescription="Short Description 1"
                    },
                    new Property
                    {
                         id = 2,
                         brand= new Brand
                         {
                             brandName = "Brand1"
                         },
                         propertyName="Property Name 1",
                         propertyStatus = new PropertyStatus
                         {
                             status="Normal"
                         },
                        shortDescription="Short Description 1"
                    },
                    new Property
                    {
                         id = 3,
                         brand= new Brand
                         {
                             brandName = "Brand1"
                         },
                         propertyName="Property Name 1",
                         propertyStatus = new PropertyStatus
                         {
                             status="Normal"
                         },
                        shortDescription="Short Description 1"
                    }
                };
                return Json(list);
            }
        }

    PropertyController: (In area "Hosts")

    [Area("Hosts")]
        public class PropertyController : Controller
        {
            public IActionResult Index()
            {
                return View();
            }
    
            public IActionResult Details(int id)
            {
                return Json(@"This is details");
            }
        }

    Index.cshtml: (In area "Hosts")

    @model IEnumerable<Property>
    
    @{
        ViewBag.Title = "Properties";
        ViewBag.Subtitle = "The backbone of your business";
        Layout = "~/Views/Shared/_Layout.cshtml";
    
    }
    
    <div id="ModalPlaceHolder"></div>
    
    <div class="row justify-content-start">
        <div class="col-xxl-6 col-xl-8">
            <div class="card">
                <div class="card-body">
                    <div class="row mb-5">
                        <div class="col-md-12">
                            <a asp-action="Create" class="btn btn-primary float-right">New Brand</a>
                        </div>
                    </div>
                    <div class="datatable">
    
                        <table id="tblData" class="table" style="100%">
                            <thead>
                                <tr>
                                    <th>Id</th>
                                    <th>Brand Name</th>
                                    <th>Property Name</th>
                                    <th>Short Description</th>
                                    <th>Status</th>
                                    <th></th>
                                </tr>
                            </thead>
                        </table>
    
                    </div>
                </div>
            </div>
        </div>
        
    </div>
    
    @section Styles{
        <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/dataTables.bootstrap4.min.css" asp-append-version="true" />
    }
    
    @section Scripts{
        <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js" asp-append-version="true"></script>
        <script src="https://cdn.datatables.net/1.10.21/js/dataTables.bootstrap4.min.js" asp-append-version="true"></script>
        <script src="~/js/properties.js" asp-append-version="true"></script>
        <script src="~/js/modal.js" asp-append-version="true"></script>
    
    }

    Properties.js

    var dataTable;
    
    $(document).ready(function () {
        loadDataTable();
    // Call the modal related function after the datatable has been drawn dataTable.on('draw', function () { PopulateModal(); }); }); function loadDataTable() { dataTable = $('#tblData').DataTable({ "ajax": { "url": "LoadData", "dataSrc": '', "type": "GET", "datatype": "json" }, "columns": [ { "data": "id" }, { "data": "brand.brandName" }, { "data": "propertyName" }, { "data": "shortDescription" }, { "data": "propertyStatus.status" }, { "data": "id", "render": function (data) { return `<div class="btn-group"> <button type="button" class="btn btn-primary btn-sm dropdown-toggle rounded-0" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Actions </button> <div class="dropdown-menu rounded-0"> <a class="dropdown-item" data-toggle="ajax-modal" data-url="/Hosts/property/Details/${data}">Details</a> <a class="dropdown-item" data-toggle="ajax-modal" data-target="#EditProperty" data-url="/Hosts/property/Edit/${data}">Edit</a> <a class="dropdown-item" data-toggle="ajax-modal" data-target="#DeleteProperty" data-url="/Hosts/property/Delete/${data}">Delete</a> </div> </div>`; } } ], "columnDefs": [ { "targets": [0], "visible": false, "searchable": false } ] }); }

    modal.js

    function PopulateModal() {
    
        var ModalPlaceHolderElement = $('#ModalPlaceHolder');
        $('a[data-toggle="ajax-modal"]').click(function (event) {
            
            var url = $(this).data('url');
            var decodedUrl = decodeURIComponent(url);
            $.get(decodedUrl).done(function (data) {
                data = data + "<br/>"
                    + "url: " + url + "<br/>"
                    + "decodedUrl: " + decodedUrl;
                ModalPlaceHolderElement.html(data);
                //ModalPlaceHolderElement.find('.modal').modal('show');
            })
        })
    
        ModalPlaceHolderElement.on('click', '[data-save="modal"]', function (event) {
            event.preventDefault();
            var form = $(this).parents('.modal').find('form');
            var actionUrl = form.attr('action');
            var sendData = form.serialize();
            $.post(actionUrl, sendData).done(function (data) {
                ModalPlaceHolderElement.find('.modal').modal('hide');
            })
        })
    
    };

    Demo:

     

    Hope this can help you.

    Best regards,

    Sean

    Monday, August 24, 2020 7:49 AM