(C# ASP.NET Core Ajax) Inline, In-place Edit, Update, Cancel of records without a page refresh

Simplest explanation of AJAX based Edit, Update, Cancel operations on a row of an HTML table. An ASP.NET Core POST handler receives the updated values that can be processed for an update to a database.
(Rev. 19-Mar-2024)

Categories | About |     |  

Parveen,

This article continues from the previous article. Please first go through the previous article - (solved)Javascript and HTML5 scheme for inplace, inline editing of records

This is the screenshot that you can refer for what we are doing -

Configure the Startup.cs File

The startup.cs file should be configured to set razor pages as the end-points for processing the HTTP requests. The following is the completed file:

using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Hosting;

using Microsoft.Extensions.DependencyInjection;

using Microsoft.Extensions.Hosting;

namespace Ajax
{

  public class Startup
  {

    public void ConfigureServices(IServiceCollection services)
    {

      // add support for razor pages 
      services.AddRazorPages();

    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {

      if (env.IsDevelopment())
      {

        app.UseDeveloperExceptionPage();

      }

      app.UseRouting();

      app.UseEndpoints(endpoints =>
      {

        // add razor pages as the end-points 
        endpoints.MapRazorPages();

      });

    }

  }

}

Video Explanation

The Razor Page Markup

The following is the mark-up for the CSHTML razor page file. It creates an html table of 3 columns. The first column is for the edit/update/cancel link anchor buttons; the second column is for the text based input, and the last column is for a boolean field. For details please refer - (solved)Javascript and HTML5 scheme for inplace, inline editing of records

@page

@model Ajax.Pages.IndexModel

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<form id="frm" method="post">

  <table border="1" style="width:75%;margin:4px auto">

    <caption><h1>In-Place Edit Example</h1></caption>

    <tr>

      <th></th>

      <th>Name</th>

      <th>IsCertified</th>

    </tr>

    <tr>

      <td>
        <a class="edit" href="javascript:">Edit</a>
      </td>

      <td>
        James
      </td>

      <td>
        No
      </td>

    </tr>

    <tr>

      <td>
        <a class="edit" href="javascript:">Edit</a>
      </td>

      <td>
        Mary
      </td>

      <td>
        Yes
      </td>

    </tr>

    <tr hidden id="boxes">

      <td>
        <a href="javascript:" id="aUpdate">Update</a>
        |
        <a href="javascript:" id="aCancel">Cancel</a>
      </td>

      <td>
        <input id="txt" name="txt" style="width:99%;" />
      </td>

      <td>
        <input type="checkbox" name="chk" id="chk" /> 
        <label>Certified</label>
      </td>

    </tr>
  </table>
</form>

<script type="text/javascript">

  (function () {

    // currently being edited tr row 
    let currentTR;

    // query all  "edit" anchors 
    document.querySelectorAll("a.edit").forEach(a => {

      // attach click event handler to each "edit" 
      a.addEventListener("click", function () {

        // cancel any pending edits 
        if (currentTR) {

          aCancel.click();

        }

        // find the parent tr of the clicked edit 
        currentTR = a.closest("tr");

        // hide the tr 
        currentTR.hidden = true;

        // insert the boxes along it 
        currentTR.insertAdjacentElement('beforebegin', boxes);

        // fill data into the inputs 
        txt.value = currentTR.cells[1].innerText.trim();
        chk.checked = currentTR.cells[2].innerText.trim().startsWith("Y");

        // show the boxes 
        boxes.hidden = false;

      });

    });

    aCancel.addEventListener("click", function () {

      boxes.hidden = true;

      currentTR.hidden = false;

    });

    aUpdate.addEventListener("click", function () {

      // aysnchronous POST the form inputs 
      fetch(frm.action,
        {
          method: frm.method,

          body: new FormData(frm)
        }
      )
        // if any exceptions - log them 
        .catch(err => console.log("network error: " + err))

        .then(response => {

          // read json from the response stream 
          // we recommend checking the status code 
          // at this point 
          response.json().then(data => {

            // hide the input controls 
            boxes.hidden = true;

            // set the values of td 
            currentTR.cells[1].innerText = txt.value;
            currentTR.cells[2].innerText = chk.checked ? "Yes" : "No";

            // show the td 
            currentTR.hidden = false;
          });
        });
    });
  })();

</script>


Explanation of the Update Handler

The update handler aUpdate . addEventListener ( "click", function sends an ajax POST request to the server and receives an OK repsonse. After that it updates the <td> cells of the table.

The status code of the response should be tested for 200 OK. For details please refer the article (C# ASP.NET Core Ajax) Authentication and Authorization with AJAX Requests

The C# Index.cshtml.cs File

We have not included the database part. You can insert a break-point to check and verify that the updated values are indeed received in the OnPost handler. See the linked video for details.

using Microsoft.AspNetCore.Mvc;

using Microsoft.AspNetCore.Mvc.RazorPages;

using System;

using System.Threading.Tasks;

namespace Ajax.Pages
{

  public class IndexModel : PageModel
  {

    public async Task<JsonResult> OnPost(String txt, bool chk)
    {

      await Task.Delay(500);

      // insert a break point to check 
      // the String txt and bool chk 
      // parameters received above 
      // your database code can be written 
      // to process these values - an ID 
      // would be required too 
      return new JsonResult("OK");

    }

  }

}


This Blog Post/Article "(C# ASP.NET Core Ajax) Inline, In-place Edit, Update, Cancel of records without a page refresh" by Parveen is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.