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:
Loading RAG configuration data
Adding a new RAG configuration
Updating an existing RAG configuration
Deleting a configuration
Changing the active or inactive status
Validating input fields
Displaying success notifications
Displaying records using DataTables
Prerequisites
Before using the code, make sure the project includes the required client-side libraries:
jQuery
Bootstrap
Bootstrap JavaScript
DataTables
DOMPurify
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:
The page loads and executes
loadData().The application sends a GET request to the
Listendpoint.The returned RAG configuration records are displayed in a DataTable.
The user can select Add New RAG to create a new record.
The
Validate()function checks the required fields.The application sends the data to the server through an AJAX POST request.
After a successful operation, the DataTable is refreshed.
The user can select an existing record and use
GetbyID()to load its details.The
Update()function sends the modified values to the server.The user can delete a record after confirming the delete operation.
The status checkbox allows the active or inactive status of a record to be changed.
Toast notifications provide feedback after successful operations.
Best Practices
When implementing a similar AJAX-based configuration interface, consider the following practices:
Validate input on both the client and server.
Sanitize dynamically generated HTML where appropriate.
Return consistent JSON responses from server endpoints.
Use meaningful function and variable names.
Handle AJAX errors instead of relying only on the success callback.
Confirm destructive operations such as deletion.
Ensure that server-side endpoints perform appropriate authorization checks.
Keep database validation independent of client-side validation.
Use HTTPS when sending application data between the browser and server.
Avoid exposing sensitive information through client-side code.
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
Provides asynchronous communication using AJAX.
Avoids full-page reloads for common CRUD operations.
Provides client-side validation.
Supports searching and pagination through DataTables.
Provides user feedback through toast notifications.
Uses a reusable function for different toast message types.
Provides confirmation before destructive operations.
Disadvantages
The implementation depends on several client-side libraries.
Dynamically constructing large HTML strings can become difficult to maintain.
Client-side validation alone is not sufficient for application security.
AJAX error handling is not included in the provided implementation.
Dynamically generated event handlers require additional care when the DataTable is redrawn.
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.

Join the conversation! Your thoughts help the community grow.