Managing configuration records through a web interface often requires common operations such as adding, updating, deleting, and changing the status of records. This article demonstrates how to implement a RAG (Red, Amber, Green) configuration management interface using jQuery, AJAX, Bootstrap, and DataTables.

The implementation uses AJAX requests to communicate with the server without requiring a full page reload. It also provides client-side validation, confirmation dialogs, toast notifications, and a searchable DataTable for displaying RAG configuration records.

In this article, we will cover the following operations:

Prerequisites

Before using the code, make sure the project includes the required client-side libraries:

The application should also provide the corresponding server-side endpoints used by the AJAX requests:

../RAGConfig/List
../RAGConfig/Add
../RAGConfig/GetbyID/{RAGID}
../RAGConfig/Update
../RAGConfig/Delete/{ID}
../RAGConfig/ChangeStatus/{ID}

These endpoints are responsible for retrieving and modifying the RAG configuration data.

Creating Toast Notifications

The application uses Bootstrap toast notifications to display operation results to users.

function ToastSuccess(Message) {
    ToastMessage('Success', Message);
}

function ToastWarning(Message) {
    ToastMessage('Warning', Message);
}

function ToastDanger(Message) {
    ToastMessage('Danger', Message);
}

function ToastInfo(Message) {
    ToastMessage('Info', Message);
}

The common ToastMessage function determines the appropriate CSS class based on the notification type.

function ToastMessage(tType, Msg) {
    var number = Math.floor(Math.random() * 90000) + 10000;

    var typeLoc = "text-bg-purple";

    if (tType.toLowerCase() == "info")
        typeLoc = "text-bg-blue";
    else if (tType.toLowerCase() == "success")
        typeLoc = "text-bg-Success";
    else if (tType.toLowerCase() == "warning")
        typeLoc = "text-bg-warning";
    else if (tType.toLowerCase() == "danger")
        typeLoc = "text-bg-danger";

    var str =
        '<div id="Toast' + tType + number +
        '" class="toast ds-toast ' + typeLoc +
        ' border-0" role="alert" aria-live="assertive" aria-atomic="true">' +
        '<div class="d-flex">' +
        '<div class="toast-body">' +
        DOMPurify.sanitize(Msg) +
        '</div>' +
        '<button type="button" class="btn-close me-2 m-auto" ' +
        'data-bs-dismiss="toast" aria-label="Close"></button>' +
        '</div>' +
        '</div>';

    $('#ToastContainer').append(str);

    const toastE = document.getElementById("Toast" + tType + number);
    const toastd = new bootstrap.Toast(toastE);

    toastd.show();
}

The DOMPurify.sanitize() method is used before inserting the message into the generated HTML. This helps sanitize dynamically generated content before it is added to the DOM.

Loading Data When the Page Loads

When the document is ready, the loadData() function is called to retrieve the existing RAG configuration records.

$(document).ready(function () {
    loadData();

    $('#btnUpdate').hide();

    $('#btnAddNew').click(function () {
        ClearTextBox();
        $('#Modal_Label').html('Add New RAG');
        $('#RAGModel').modal('show');
    });

    $('#btnUpdate').click(function () {
        Update();
    });

    $('#btnAdd').click(function () {
        Add();
    });
});

The loadData() function sends a GET request to the List endpoint.

function loadData() {
    $.ajax({
        url: "../RAGConfig/List",
        type: "GET",
        contentType: "application/json;charset=utf-8",
        dataType: "json",
        success: function (Data) {
            if (AjaxSuccess(Data)) {
                // Build and display the table
            }
        }
    });
}

The response is used to dynamically construct an HTML table. Each record can contain information such as the RAG name, description, CSS class, hexadecimal color value, date, creation date, status, and available actions.

The records are processed using jQuery's $.each() method.

$.each(Data.ResponseData, function (key, item) {
    html += '<tr>';
    html += '<td>' + item.Row + '</td>';
    html += '<td>' + item.RAG + '</td>';
    html += '<td>' + item.Discription + '</td>';
    html += '<td>' + item.CssClassName + '</td>';
    html += '<td>' + item.ColorHexaValue + '</td>';
    html += '<td>' + item.ShowDate + '</td>';
    html += '<td>' + item.CreatedOn + '</td>';
    html += '</tr>';
});

After the HTML is generated, it is inserted into the page.

$('#RAG_Data div').html('');
$('#RAG_Data').append(DOMPurify.sanitize(html));
$('#RAG_Data').show();

The DataTables plugin is then initialized to provide searching, pagination, and other table functionality.

$('#RAGTable').DataTable({
    fixedHeader: true,
    bFilter: true,
    ordering: false,
    paging: true,
    searching: true,
    info: true,
    destroy: true,
    language: {
        sLengthMenu: "_MENU_",
        searchPlaceholder: 'Search by Service Name'
    }
});

Adding a New RAG Configuration

The Add() function is used to create a new RAG configuration. Before sending the data to the server, it calls the Validate() function to check the required fields.

function Add() {
    var res = Validate();

    if (res == false) {
        return false;
    }

    var pageObj = {
        Status: 0,
        RAG: TrimData($('#RAG').val()),
        Discription: TrimData($('#Discription').val()),
        CssClassName: TrimData($("#CssClassName").val()),
        ColorHexaValue: TrimData($("#ColorHexaValue").val())
    };

    // AJAX request
}

The values entered by the user are stored in the pageObj object. The object is converted into JSON using JSON.stringify() and sent to the server using an AJAX POST request.

$.ajax({
    url: "../RAGConfig/Add",
    data: JSON.stringify(pageObj),
    type: "POST",
    contentType: "application/json;charset=utf-8",
    dataType: "json",
    success: function (Data) {
        if (AjaxSuccess(Data)) {
            ToastSuccess('Success! - ' + Data.ResponseText);
            loadData();
            $('#RAGModel').modal('hide');
        }
    }
});

After a successful response, the table is refreshed and the modal is closed.

Retrieving a RAG Record for Editing

When the user selects the edit option, the GetbyID() function retrieves the selected record using its RAG ID.

function GetbyID(RAGID) {
    $('#RAG').removeClass('border-red').addClass('border-green');
    $('#Discription').removeClass('border-red').addClass('border-green');
    $('#CssClassName').removeClass('border-red').addClass('border-green');
    $('#ColorHexaValue').removeClass('border-red').addClass('border-green');

    $.ajax({
        url: "../RAGConfig/GetbyID/" + RAGID,
        type: "GET",
        contentType: "application/json;charset=UTF-8",
        dataType: "json",
        success: function (Data) {
            if (AjaxSuccess(Data)) {
                ClearTextBox();

                $('#Modal_Label').html('Update RAG');
                $('#RAG').val(Data.ResponseData[0].RAG);
                $('#Discription').val(Data.ResponseData[0].Discription);
                $('#RAGID').val(Data.ResponseData[0].RAGID);
                $('#CssClassName').val(Data.ResponseData[0].CssClassName);
                $('#ColorHexaValue').val(Data.ResponseData[0].ColorHexaValue);

                $('#RAGModel').modal('show');
                $('#btnUpdate').show();
                $('#btnAdd').hide();
            }
        }
    });

    return false;
}

The returned values are assigned to their respective form fields. The same modal can then be used to update the selected record.

Updating a RAG Configuration

The Update() function is responsible for updating an existing RAG configuration.

First, it validates the input fields.

function Update() {
    var res = Validate();

    if (res == false) {
        return false;
    }

    var empObj = {
        Status: 0,
        RAG: TrimData($('#RAG').val()),
        Discription: TrimData($('#Discription').val()),
        RAGID: TrimData($('#RAGID').val()),
        CssClassName: TrimData($("#CssClassName").val()),
        ColorHexaValue: TrimData($("#ColorHexaValue").val())
    };

    // AJAX request
}

The updated values are stored in the empObj object and sent to the update endpoint.

$.ajax({
    url: "../RAGConfig/Update",
    data: JSON.stringify(empObj),
    type: "POST",
    contentType: "application/json;charset=utf-8",
    dataType: "json",
    success: function (Data) {
        if (AjaxSuccess(Data)) {
            ToastSuccess('Success! - ' + Data.ResponseText);
            loadData();
            $('#RAGModel').modal('hide');
            ClearTextBox();
        }
    }
});

After the update succeeds, the table is reloaded and the form is cleared.

Deleting a RAG Configuration

The Delele() function is used to delete a RAG configuration. A confirmation dialog is displayed before the delete request is sent.

function Delele(ID) {
    var ans = confirm("Are you sure you want to delete this Record?");

    if (ans) {
        $.ajax({
            url: "../RAGConfig/Delete/" + ID,
            type: "POST",
            contentType: "application/json;charset=UTF-8",
            dataType: "json",
            success: function (Data) {
                if (AjaxSuccess(Data)) {
                    loadData();
                    ToastSuccess('Success! - ' + Data.ResponseText);
                }
            }
        });
    }
}

The confirmation step helps prevent accidental deletion of a record.

Clearing the Form

The ClearTextBox() function resets the form after adding or updating a record.

function ClearTextBox() {
    $('#RAGID').val("");
    $('#RAG').val("");
    $('#Discription').val("");
    $('#CssClassName').val("");

    $('#btnUpdate').hide();
    $('#btnAdd').show();

    $('#RAG').removeClass('border-green');
    $('#Discription').removeClass('border-green');
    $('#CssClassName').removeClass('border-green');
    $('#ColorHexaValue').removeClass('border-green');

    $('#RAG').removeClass('border-red');
    $('#Discription').removeClass('border-red');
    $('#CssClassName').removeClass('border-red');
    $('#ColorHexaValue').removeClass('border-red');
}

This method clears the existing values and restores the form to its initial state.

Validating the Input Fields

The Validate() function performs client-side validation of the required fields.

function Validate() {
    var isValid = true;

    if (TrimData($('#RAG').val()) == "") {
        $('#RAG').removeClass('border-green').addClass('border-red');
        isValid = false;
    }
    else {
        $('#RAG').removeClass('border-red').addClass('border-green');
    }

    if (TrimData($('#Discription').val()) == "") {
        $('#Discription').removeClass('border-green').addClass('border-red');
        isValid = false;
        return isValid;
    }
    else {
        $('#Discription').removeClass('border-red').addClass('border-green');
    }

    if (TrimData($('#CssClassName').val()) == "") {
        $('#CssClassName').removeClass('border-green').addClass('border-red');
        isValid = false;
        return isValid;
    }
    else {
        $('#CssClassName').removeClass('border-red').addClass('border-green');
    }

    if (TrimData($('#ColorHexaValue').val()) == "") {
        $('#ColorHexaValue').removeClass('border-green').addClass('border-red');
        isValid = false;
        return isValid;
    }
    else {
        $('#ColorHexaValue').removeClass('border-red').addClass('border-green');
    }

    return isValid;
}

A red border indicates that a required field is empty, while a green border indicates that the field has passed the client-side validation.

Client-side validation improves the user experience, but server-side validation should also be implemented because client-side validation can be bypassed.

Changing the RAG Status

The status of a RAG configuration can be changed using the checkbox displayed in the table.

function OnChangeEvent(e) {
    var ans = confirm("Are you sure you want to change the status?");

    if (ans) {
        $.ajax({
            url: "../RAGConfig/ChangeStatus/" + e,
            type: "POST",
            contentType: "application/json;charset=UTF-8",
            dataType: "json",
            success: function (Data) {
                if (AjaxSuccess(Data)) {
                    loadData();
                    ToastSuccess('Success! - ' + Data.ResponseText);
                }
            }
        });
    }
    else {
        loadData();
    }
}

If the user confirms the change, the application sends a POST request to the ChangeStatus endpoint. If the user cancels the operation, the table is reloaded to restore the previous state.

Output

After the page loads successfully, the RAG configurations are displayed in a searchable and paginated DataTable.

The table contains the following columns:

Column

Description

SN

Displays the row number

RAG

Displays the RAG configuration name

Description

Displays the configuration description

CSS Class Name

Displays the CSS class associated with the RAG

Color Hexa Value

Displays the hexadecimal color value

Date

Displays the configured date

CreatedOn

Displays the record creation date

Status

Allows the RAG status to be changed

Action

Provides edit and delete operations

When a user successfully adds or updates a record, a toast notification displays the response returned by the server.

The edit action loads the selected record into the modal. The delete action displays a confirmation dialog before deleting the selected record. The status checkbox allows the user to change the status of an existing configuration.

Complete Workflow

The complete workflow of the application is as follows:

  1. The page loads and executes loadData().

  2. The application sends a GET request to the List endpoint.

  3. The returned RAG configuration records are displayed in a DataTable.

  4. The user can select Add New RAG to create a new record.

  5. The Validate() function checks the required fields.

  6. The application sends the data to the server through an AJAX POST request.

  7. After a successful operation, the DataTable is refreshed.

  8. The user can select an existing record and use GetbyID() to load its details.

  9. The Update() function sends the modified values to the server.

  10. The user can delete a record after confirming the delete operation.

  11. The status checkbox allows the active or inactive status of a record to be changed.

  12. Toast notifications provide feedback after successful operations.

Best Practices

When implementing a similar AJAX-based configuration interface, consider the following practices:

Common Issues and Troubleshooting

DataTable Does Not Load

Check whether the List endpoint is returning valid JSON. You can also use the browser's developer tools and inspect the Network tab to verify the AJAX response.

Add or Update Does Not Work

Verify that all required fields pass validation and that the JSON object sent by the client matches the model expected by the server.

Toast Notification Does Not Appear

Make sure Bootstrap's JavaScript bundle is loaded and that an element with the ToastContainer ID exists on the page.

Edit Button Does Not Work

Check that the generated edit element uses the expected EditRAG_ ID prefix and that the RAG ID being passed to GetbyID() is valid.

Delete Operation Fails

Verify that the Delete/{ID} endpoint accepts the HTTP method being used and that the supplied ID corresponds to an existing record.

Advantages

Disadvantages

Conclusion

This implementation demonstrates how jQuery AJAX can be used to build a RAG configuration management interface without requiring a full page refresh for every operation. The application supports loading, adding, editing, deleting, and changing the status of RAG records while providing client-side validation, confirmation dialogs, DataTables functionality, and toast notifications.

The same approach can be adapted for other administrative configuration screens where records need to be managed through a web interface. For production applications, client-side validation should be complemented with server-side validation, authorization, proper error handling, and secure API design.