Как отобразить ошибку JQuery Datatable в div с предупреждением-предупреждением при загрузке, а не в окне предупреждения - PullRequest
0 голосов
/ 21 ноября 2018

Я работаю на веб-сайте ASP.NET Core 2.1 и использую Datatables.net для отображения моих списков записей, полученных из внутреннего API.

Эта проблема, которую я пытаюсь решить, заключается в том, что всякий раз, когда возникает ошибка при извлечении данных из бэкэнд-API, я хочу, чтобы сообщение об ошибке появилось в DIV Bootstrap alert-error на той же странице, что и датируемый,

Я смотрел на https://datatables.net/forums/discussion/30033/override-default-ajax-error-behavior и Включить предупреждающее предупреждение о наличии данных , но я не силен в javascript, поэтому мне сложно определить, как реализовать эту функцию.

В настоящее время у меня есть настраиваемая таблица данных на моей странице cshtml следующим образом:

<script>

    jQuery(document).ready(function ($) {

        var table = $("#sitelist").DataTable({
            "processing": true,
            "serverSide": true,
            "filter": true,
            "orderMulti": false,
            "ajax": {
                "url": "/Sites/LoadData",
                "type": "POST",
                "datatype": "json"
            },
            "columnDefs": [
                { "orderable": false, "targets": 6 },
                { "className": "text-center", "targets": [4, 5] },
                {
                    "targets": [4, 5],
                    "createdCell": function(td, cellData, rowData, row, col) {
                        if (cellData) {
                            $(td).html('<i class="far fa-check-circle text-primary""></i>');
                        } else {
                            $(td).html('<i class="far fa-times-circle text-danger""></i>');
                        }
                    }
                }
            ],
            "columns": [
                { "data": "Id", "name": "Id", "autoWidth": true, "defaultContent": "" },
                { "data": "SiteName", "name": "SiteName", "autoWidth": true, "defaultContent": "" },
                { "data": "CompanyId", "name": "CompanyId", "autoWidth": true, "defaultContent": "" },
                { "data": "CompanyName", "name": "CompanyName", "autoWidth": true, "defaultContent": "" },
                { "data": "IsAdminSite", "name": "IsAdminSite", "autoWidth": true, "defaultContent": "" },
                { "data": "IsEnabled", "name": "IsEnabled", "autoWidth": true, "defaultContent": "" },
                {
                    "render": function (data, type, full, meta) { return `<a href="/sites/edit?id=${full.Id}"><i class="far fa-edit text-primary" title="Edit"></a>`; }
                }
            ],
            // From StackOverflow http://stackoverflow.com/a/33377633/1988326 - hides pagination if only 1 page
            "preDrawCallback": function (settings) {
                var api = new $.fn.dataTable.Api(settings);
                var pagination = $(this)
                    .closest('.dataTables_wrapper')
                    .find('.dataTables_paginate');
                pagination.toggle(api.page.info().pages > 1);
            }

        });

    });


</script>

А вот действие loaddata в моем классе SitesController;

    public async Task<IActionResult> LoadData()
    {
        try
        {
            await SetCurrentUser();
            ViewData["Role"] = _currentRole;

            var draw = HttpContext.Request.Form["draw"].FirstOrDefault();
            var start = Request.Form["start"].FirstOrDefault();
            var length = Request.Form["length"].FirstOrDefault();
            var sortColumn = Request.Form["columns[" + Request.Form["order[0][column]"].FirstOrDefault() + "][name]"].FirstOrDefault();
            var sortColumnDirection = Request.Form["order[0][dir]"].FirstOrDefault();
            var searchValue = Request.Form["search[value]"].FirstOrDefault();
            var pageSize = length != null ? Convert.ToInt32(length) : 0;
            var skip = start != null ? Convert.ToInt32(start) : 0;
            var request = new SitesGetListRequest
            {
                OrderBy = SetOrderBy(sortColumn, sortColumnDirection),
                Filter = SetFilter(searchValue),
                PageNumber = (skip / pageSize) + 1,
                PageSize = pageSize
            };
            var tokenSource = new CancellationTokenSource();
            var token = tokenSource.Token;

            var endpoint = $"api/companies/{SetCompanyId()}/sites/filtered";
            var siteData = await _client.GetSiteListAsync(request, endpoint, token);
            if (siteData.Sites != null)
            {
                return Json(new
                {
                    draw,
                    recordsFiltered = siteData.Paging.TotalCount,
                    recordsTotal = siteData.Paging.TotalCount,
                    data = siteData.Sites.ToList()
                });
            }
            //TODO: Find a way to pass error to a Bootstrap alert-warning DIV rather than the jQuery (javascript) alert box
            var errorMessage = $"Http Status Code: {siteData.StatusCode} - {siteData.ErrorMessages.FirstOrDefault()}";
            return Json(new
            {
                data = "",
                error = errorMessage
            });

        }
        catch (Exception ex)
        {
            const string message = "An exception has occurred trying to get the list of Site records.";
            _logger.LogError(ex, message);
            throw;
        }
    }

Как естьпрямо сейчас, если существует ошибка в объекте, возвращенном из вызова API, я передаю сообщение свойству error в возвращенном json, и оно отображается в виде всплывающего окна с предупреждением JavaScript на моей странице cshtml, и когда я нажимаю кнопку ОК,отображает «Записи не найдены», как показано на изображениях ниже;

Popup Alert on Error

и ...

After popup alert is cleared.

Я хочу, чтобы сообщение об ошибке отображалось в загрузочном блоке оповещения об опасности в верхней части страницы cshtml.Я не хочу, чтобы появлялось всплывающее окно с предупреждением, и я все еще хочу, чтобы в элементе данных отображалось «Записи не найдены».

Я думаю, что то, что я ищу, описано в Включить предупреждение о датируемом предупреждении ...

Отключите всплывающее окно оповещения с помощью

$.fn.dataTable.ext.errMode = 'none';

и передайте сообщение об ошибке в Div BootStrap, используя

 $('#example')
.on( 'error.dt', function ( e, settings, techNote, message ) {
    console.log( 'An error has been reported by DataTables: ', message );
} )
.DataTable();

, но вместо

console.log( 'An error has been reported by DataTables: ', message );

используйте что-то вроде

$("#error").html(MY ERROR MESSAGE HERE);

и присвойте id = "error" элементу начальной загрузки.

Но я не могу понять, как вызвать вызов Ajax измой метод loaddata в SitesController, а также как правильно добавить событие ошибки в начало моего сценария с данными.

Прежде чем я потратил больше времени, пытаясь решить эту проблему, я решил поставить это на SO и посмотретьесли кто-то с опытом работы с javascrit / jquery может дать некоторые рекомендации.

1 Ответ

0 голосов
/ 21 ноября 2018

Вы можете добавить свойство error к вызову ajax.Вероятно, лучше всего будет использовать fnServerData .

    jQuery(document).ready(function ($) {

        var table = $("#sitelist").DataTable({
            "processing": true,
            "serverSide": true,
            "filter": true,
            "orderMulti": false,
            "sAjaxSource": "/Sites/LoadData",
            "fnServerData": function (sSource, aoData, fnCallback) {
                $.ajax({
                   "dataType": 'json',
                    "type": "GET",
                    "url": sSource,
                    "data": aoData,
                    "cache": false,
                     "success": function (data) {
                          fnCallback(data);                   
                      },
                     "error": function(error){
                        $("#error").html(error);
                     }
                });
             },
            "columnDefs": [
                { "orderable": false, "targets": 6 },
                { "className": "text-center", "targets": [4, 5] },
                {
                    "targets": [4, 5],
                    "createdCell": function(td, cellData, rowData, row, col) {
                        if (cellData) {
                            $(td).html('<i class="far fa-check-circle text-primary""></i>');
                        } else {
                            $(td).html('<i class="far fa-times-circle text-danger""></i>');
                        }
                    }
                }
            ],
            "columns": [
                { "data": "Id", "name": "Id", "autoWidth": true, "defaultContent": "" },
                { "data": "SiteName", "name": "SiteName", "autoWidth": true, "defaultContent": "" },
                { "data": "CompanyId", "name": "CompanyId", "autoWidth": true, "defaultContent": "" },
                { "data": "CompanyName", "name": "CompanyName", "autoWidth": true, "defaultContent": "" },
                { "data": "IsAdminSite", "name": "IsAdminSite", "autoWidth": true, "defaultContent": "" },
                { "data": "IsEnabled", "name": "IsEnabled", "autoWidth": true, "defaultContent": "" },
                {
                    "render": function (data, type, full, meta) { return `<a href="/sites/edit?id=${full.Id}"><i class="far fa-edit text-primary" title="Edit"></a>`; }
                }
            ],
            // From StackOverflow http://stackoverflow.com/a/33377633/1988326 - hides pagination if only 1 page
            "preDrawCallback": function (settings) {
                var api = new $.fn.dataTable.Api(settings);
                var pagination = $(this)
                    .closest('.dataTables_wrapper')
                    .find('.dataTables_paginate');
                pagination.toggle(api.page.info().pages > 1);
            }

        });

    });


</script>
...