Saturday, July 15, 2023

ASP.NET Core - Admin Panel in Razor Page using Fetch API


Objectives. In this project, we learn about 
  • JavaScript querySelectorAll method
  • JavaScript forEach method
  • JavaScript addEventListener method 
  • JavaScript fetch method 

Project
  • Open the Visual Studio. 
  • Create web project using ASP.NET Core Empty template.
  • Project name: AdminPanelRP
  • Solution name: AdminPanelRP
  • .NET Core version: 5.0
  • Add the AddRazorPages() into the IServiceCollection in Startup class.
  • Use MapRazorPages() as terminal middleware in Startup class.
Look at the below updated code in Startup class.
Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace AdminPanelRP
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }
    }
}
  • Add a New Folder and rename it Pages.
  • Add a Razor Page in Pages folder and name it Index. Two files are generated which are Index.cshtml and Index.cshtml.cs
Next step. Update the Index.cshtml to create a list of tasks in the table. Add the JavaScript code to handle the event occured due to selection change in the dropdown. Note that the handler is ChangedCountry and method is GET, so we have OnGetChangedCountry action in the code behind Index.cshtml.cs file. The name of parameter is name. The name must be the same in handler action method as well.   
Index.cshtml

@page
@model AdminPanelRP.Pages.IndexModel
@{
}
<style>
    li {
        background-color: darkblue;
        padding: 4px;
        margin: 4px;
        display: block;
    }

    a[report] {
        color: white;
        font-family: Broadway;
        text-transform: capitalize;
    }

    .outer {
        background-color: black;
    }

    .first {
        height: 90%;
        margin-left: 20px;
        background-color: fuchsia;
        float: left;
    }

    .second {
        width: 80%;
        height: 90%;
        background-color: brown;
        float: left;
    }

    body {
        background-color: darkseagreen;
    }
</style>
<div class="outer">
    <h3 style="text-align:center; padding:5px; color:white;font-family:Georgia;font-size:30px;">ASP.NET Core - Admin Panel in Razor Page using Fetch API</h3>
    <div class="first">
        <ul>
            <li><a report="r1" href="#">Students Report</a></li>
            <li><a report="r2" href="#">Teachers Salary</a></li>
            <li><a report="r3" href="#">HR Department</a></li>
            <li><a report="r4" href="#">Conferences</a></li>
        </ul>
    </div>
    <div class="second">
    </div>
</div>

<script type="text/javascript">
    window.onload = function () {
        var tick = document.createElement("span");
        tick.style.font.bold();
        tick.innerHTML = "\u2713";
        var reports = document.querySelectorAll("a");
        reports.forEach(r => {
            r.innerHTML = tick.innerHTML + "&nbsp;&nbsp;" + r.innerHTML
        });
    }
</script>

The UI of the Admin Panel:

Logic of Report Display in Right panel:

We will update the code so that when admin clicks on a report link in the left panel then its report will be displayed in the right panel. The  document.querySelectorAll helps to query all the anchors and then we get the id of the anchor which is clicked to display report.

The querySelector() method returns the first element that matches a CSS selector given in the method parameter. For example, document.querySelector("p"); gets the first parameter from the document. The querySelectorAll() method returns all elements that matches a CSS selector(s).

Index.cshtml partially updated: Add the following script to test the script.


<script type="text/javascript">
    (function () {
        // decide which anchor was clicked
        document.querySelectorAll('a[report]').forEach(anchr => {
            // addEventListener on that anchor
           anchr.addEventListener('click', function(event){
               alert("clicked");
           })
        })
    })();
</script>

If alert method works, replace it by the following code.

Index.cshtml final update:


@page
@model AdminPanelRP.Pages.IndexModel
@{
}
<style>
    li {
        background-color: darkblue;
        padding: 4px;
        margin: 4px;
        display: block;
    }

    a[report] {
        color: white;
        font-family: Broadway;
        text-transform: capitalize;
    }

    .outer {
        background-color: black;
    }

    .first {
        height: 90%;
        margin-left: 20px;
        background-color: fuchsia;
        float: left;
    }

    .second {
        width: 80%;
        height: 90%;
        background-color: brown;
        float: left;
    }

    body {
        background-color: darkseagreen;
    }
</style>

<div class="outer">
    <h3 style="text-align:center; padding:5px; color:white;font-family:Georgia;font-size:30px;">ASP.NET Core - Admin Panel in Razor Page using Fetch API</h3>

    <div class="first">
        <ul>
            <li><a report="r1" href="#">Students Report</a></li>
            <li><a report="r2" href="#">Teachers Salary</a></li>
            <li><a report="r3" href="#">HR Department</a></li>
            <li><a report="r4" href="#">Conferences</a></li>
        </ul>
    </div>
    <div class="second">
        <div id="report" style="font-family:Arial, Helvetica, sans-serif;color:white;margin-left:30px;"> <h1>Click a link in left panel.</h1></div>
    </div>
</div>
<script type="text/javascript">
    (function () {
        // decide which anchor was clicked
        document.querySelectorAll('a[report]').forEach(anchr => {
            // addEventListener on that anchor
            anchr.addEventListener('click', async function (event) {
                fetch("/?handler=GenerateReport&reportid=" + anchr.getAttribute('report'),
                    {
                        method: 'GET'
                    }).catch(err => console.log("Error during reporting: " + err))
                    .then(response => {
                        response.json()
                            .then(data => {
                                report.innerHTML = "<h1>" + data + "</h1>";
                            })
                    })
            })
        })
    })();
</script>
<script type="text/javascript">
    window.onload = function () {
        var tick = document.createElement("span");
        tick.style.font.bold();
        tick.innerHTML = "\u2713";
        var reports = document.querySelectorAll("a");
        reports.forEach(r => {
            r.innerHTML = tick.innerHTML + "&nbsp;&nbsp;" + r.innerHTML
        });
    }
</script>

Index.cshtml.cs final Update


using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Security.AccessControl;
using System.Text.Json;
using System.Threading.Tasks;

namespace AdminPanelRP.Pages
{
    public class IndexModel : PageModel
    {
        public string msg { get; set; }
        public async Task<JsonResult> OnGetGenerateReport(string reportid)
        {
            await Task.Delay(1000);
            switch (reportid)
            {
                case "r1":
                    {
                        msg = "Student Report generated";
                    }
                    break;
                case "r2":
                    {
                        msg = "Teachers Salary Report generated";
                    }
                    break;
                case "r3":
                    {
                        msg = "HR Department Report generated";
                    }
                    break;
                case "r4":
                    {
                        msg = "Conference Report generated";
                    }
                    break;
                    default:
                    {
                        msg = "Error: Report not generated";
                    }
                    break;
            }
            return new JsonResult(msg);
        }
    }
}

Run the application. We get the following output.

No comments:

Post a Comment

Hot Topics