List of Countries - Editing - Code

Client > Pages > CountryListPage.razor

@page "/countrylist"
@inject ICountryService CountryService;
@inject NavigationManager NavigationManager;
@using Syncfusion.Blazor.Popups
@inject SfDialogService DialogService

<PageTitle>Countries List</PageTitle>

<h3>Countries List</h3>

<SfGrid DataSource="@countries"
        Toolbar="Toolbaritems">
    <GridEvents OnToolbarClick="ToolbarClickHandler" TValue="Country" RowSelected="RowSelectHandler"></GridEvents>
    <GridColumns>
        <GridColumn Field="@nameof(Country.CountryId)"
                    HeaderText="Country ID"
                    TextAlign="@TextAlign.Left"
                    Width="20">
        </GridColumn>
        <GridColumn Field="@nameof(Country.CountryName)"
                    HeaderText="Country Name"
                    TextAlign="@TextAlign.Left"
                    Width="80">
        </GridColumn>
    </GridColumns>
</SfGrid>

@code {
    private List<ItemModel> Toolbaritems = new List<ItemModel>();  //provides the list to populate the toolbar items
    public List<Country>? countries;
    private int CountryID = 0;
    private string CountryName = string.Empty;

    protected override async Task OnInitializedAsync()
    {
        //Add options for the custom toolbar
        Toolbaritems.Add(new ItemModel() { Text = "Add", TooltipText = "Add a new country", PrefixIcon = "e-add" });
        Toolbaritems.Add(new ItemModel() { Text = "Edit", TooltipText = "Edit selected country", PrefixIcon = "e-edit" });
        Toolbaritems.Add(new ItemModel() { Text = "Delete", TooltipText = "Delete selected country", PrefixIcon = "e-delete" });

        await RefreshCountriesGrid();
    }

    public async Task ToolbarClickHandler(Syncfusion.Blazor.Navigations.ClickEventArgs args)
    {
        if (args.Item.Text == "Add")
        {
            //Code for adding goes here
            CountryID = 0;
            NavigationManager.NavigateTo($"/countriesaddedit/{CountryID}");
        }
        if (args.Item.Text == "Edit")
        {
            //Check that the user has selected a row
            if (CountryID == 0)
            {
                await DialogService.AlertAsync("Please select a country.", "No Country Selected");
            }
            else
            {
                NavigationManager.NavigateTo($"/countriesaddedit/{CountryID}");
                CountryID = 0;
            }
        }

        if (args.Item.Text == "Delete")
        {
            //Check that the user has selected a row
            if (CountryID == 0)
            {
                await DialogService.AlertAsync("Please select a country.", "No Country Selected");
            }
            else
            {
                //code for deleting
                string dialogMessage = $"Are you sure you want to delete {CountryName}?";
                bool isConfirm = await DialogService.ConfirmAsync(dialogMessage, "Delete Country");
                if (isConfirm)
                {
                    await CountryService.CountryDelete(CountryID);
                    await RefreshCountriesGrid();
                    CountryID = 0;
                }
            }
        }
    }

    public void RowSelectHandler(RowSelectEventArgs<Country> args)
    {
        //{args.Data} returns the current selected record.
        CountryID = args.Data.CountryId;
        CountryName = args.Data.CountryName;
    }

    public async Task RefreshCountriesGrid()
    {
        await CountryService.GetCountries();
        countries = new();
        foreach (var country in CountryService.Countries)
            countries.Add(country);
    }
}

Client > Pages > CountriesAddEditPage.razor

@page "/countriesaddedit/{CountryId:int}"

@inject ICountryService CountryService
@inject NavigationManager NavigationManager

<PageTitle>@pagetitle</PageTitle>

<h1>@pagetitle</h1>

<SfDialog IsModal="true" Width="500px" ShowCloseIcon="false" Visible="true">

    <h5>@pagetitle</h5>
    <br />
    <EditForm Model="@country" OnValidSubmit="@CountriesSave">
        <div>
            <SfTextBox Enabled="true" Placeholder="Country"
                       FloatLabelType="@FloatLabelType.Always"
                       @bind-Value="country.CountryName"></SfTextBox>
        </div>
        <br /><br />
        <div class="e-footer-content">
            <div class="button-container">
                <button type="submit" class="e-btn e-normal e-primary">Save</button>
                <button type="button" class="e-btn e-normal" @onclick="@Cancel">Cancel</button>
            </div>
        </div>
    </EditForm>
</SfDialog>

@code {
    // Create a new, empty Country   object
    public Country? country = new Country();
    public string pagetitle = "Add a Country";

    [Parameter]
    public int CountryId { get; set; }

    //Executes on page open, sets headings and gets data in the case of edit
    protected override async Task OnInitializedAsync()
    {
        if (CountryId == 0)
        {
            pagetitle = "Add a Country";
        }
        else
        {
            pagetitle = "Edit a Country";
            country = await CountryService.GetCountryById(CountryId);
        }
    }

    // Executes OnValidSubmit of EditForm above.
    protected async Task CountriesSave()
    {
        if (CountryId == 0)
        {
            await CountryService.CountryInsert(country);
            NavigationManager.NavigateTo("/countrylist");
        }
        else
        {
            await CountryService.CountryUpdate(CountryId, country);
            NavigationManager.NavigateTo("/countrylist");
        }
    }

    //Executes if user clicks the Cancel button.
    void Cancel()
    {
        NavigationManager.NavigateTo("/countrylist");
    }

}

Client > Services > CountryService > CountriesService.cs

using System.Net.Http.Json;

namespace BlazorCountriesWasm.Client.Services.CountryService
{
    public class CountryService : ICountryService
    {
        private readonly HttpClient _http;
        public CountryService(HttpClient http)
        {
            _http = http;
        }

        public List<Country> Countries { get; set; } = new List<Country>();
        public HttpClient? Http { get; }        //? here gets rid of green squiggly on "Public CountryService(HttpClient http)"

        public async Task GetCountries()
        {
            var result = await _http.GetFromJsonAsync<List<Country>>("api/country");
            if (result != null)
                Countries = result;
        }
        public async Task<Country> GetCountryById(int id)
        {
            var result = await _http.GetFromJsonAsync<Country>($"api/country/{id}");
            return result;
        }
        public async Task CountryInsert(Country country)
        {
            var result = await _http.PostAsJsonAsync("api/country/", country);
        }
        public async Task CountryUpdate(int Countryid, Country country)
        {
            var result = await _http.PutAsJsonAsync($"api/country/{Countryid}", country);
        }
        public async Task CountryDelete(int Countryid)
        {
            var result = await _http.DeleteAsync($"api/country/{Countryid}");
        }

    }
}

Client > Services > CountryService > ICountriesService.cs

namespace BlazorCountriesWasm.Client.Services.CountryService
{
    public interface ICountryService
    {
        List<Country> Countries { get; set; }

        Task GetCountries();
        Task CountryInsert(Country country);
        Task<Country> GetCountryById(int Countryid);
        Task CountryUpdate(int Countryid, Country country);
        Task CountryDelete(int Countryid);
    }
}

Server > Controllers > CountryController.cs

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Dapper;
using System.Data;
using System.Data.SQLite;

namespace BlazorCountriesWasm.Server.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class CountryController : ControllerBase
    {
        private readonly IConfiguration _config;
        public CountryController(IConfiguration config)
        {
            _config = config;
        }

        public string connectionId = "Default";
        public string sqlCommand = "";
        IEnumerable<Country>? countries;

        [HttpGet]
        public async Task<ActionResult<List<Country>>> GetCountries()
        {
            sqlCommand = "Select * From Country";
            using IDbConnection conn = new SQLiteConnection(_config.GetConnectionString(connectionId));
            {
                countries = await conn.QueryAsync<Country>(sqlCommand);
            }
            return Ok(countries);
        }

        [HttpGet("{CountryId}")]
        //[Route("{CountryId}")]
        //Or you can combine the two lines as: [HttpGet("{CountryId}")]
        public async Task<ActionResult<Country>> GetCountryById(int CountryId)
        {
            var parameters = new DynamicParameters();
            parameters.Add("@CountryId", CountryId, DbType.Int32);

            sqlCommand = $"Select * From Country " +
                "Where CountryId =  @CountryId";

            using IDbConnection conn = new SQLiteConnection(_config.GetConnectionString(connectionId));
            {
                var country = await conn.QueryFirstAsync<Country>(sqlCommand, parameters);
                return Ok(country);
            }
        }

        [HttpPost]
        public async Task<ActionResult> CountryInsert(Country country)
        {
            var parameters = new DynamicParameters();
            parameters.Add("CountryName", country.CountryName, DbType.String);

            sqlCommand = "Insert into Country (CountryName) values(@CountryName)";
            using IDbConnection conn = new SQLiteConnection(_config.GetConnectionString(connectionId));
            {
                await conn.ExecuteAsync(sqlCommand, parameters);
            }
            return Ok();
        }

        [HttpPut("{CountryId}")]
        public async Task<ActionResult> CountryUpdate(Country country)
        {
            var parameters = new DynamicParameters();
            parameters.Add("CountryId", country.CountryId, DbType.Int32);
            parameters.Add("CountryName", country.CountryName, DbType.String);

            sqlCommand =
                "Update Country " +
                "set CountryName = @CountryName " +
                "Where CountryId = @CountryId";
            using IDbConnection conn = new SQLiteConnection(_config.GetConnectionString(connectionId));
            {
                await conn.ExecuteAsync(sqlCommand, parameters);
            }
            return Ok();
        }

        [HttpDelete("{CountryId}")]
        public async Task<ActionResult> CountryDelete(int CountryId)
        {
            var parameters = new DynamicParameters();
            parameters.Add("CountryId", CountryId, DbType.Int32);

            sqlCommand =
                "Delete From Country " +
                "Where CountryId = @CountryId";
            using IDbConnection conn = new SQLiteConnection(_config.GetConnectionString(connectionId));
            {
                await conn.ExecuteAsync(sqlCommand, parameters);
            }
            return Ok();
        }

    }
}
  

Client > Program.cs

global using BlazorCountriesWasm.Client.Services.CountryService;
global using BlazorCountriesWasm.Shared;
using BlazorCountriesWasm.Client;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Syncfusion.Blazor;
using Syncfusion.Blazor.Popups;

// Register Syncfusion license
Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("Your Licence Key");

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped<ICountryService, CountryService>();
builder.Services.AddSyncfusionBlazor();
builder.Services.AddScoped<SfDialogService>();

await builder.Build().RunAsync();

Client > Shared > MainLayout.Razor

@inherits LayoutComponentBase

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <main>
        <div class="top-row px-4">
            <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
        </div>

        <article class="content px-4">
            @Body
            <Syncfusion.Blazor.Popups.SfDialogProvider />
        </article>
    </main>
</div>

Client > _Imports.razor

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using BlazorCountriesWasm.Client
@using BlazorCountriesWasm.Client.Shared
@using BlazorCountriesWasm.Client.Services.CountryService
@using Syncfusion.Blazor
@using Syncfusion.Blazor.Buttons
@using Syncfusion.Blazor.DropDowns
@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.Inputs
@using Syncfusion.Blazor.Lists
@using Syncfusion.Blazor.Navigations
@using Syncfusion.Blazor.Notifications
@using Syncfusion.Blazor.Popups