I am new to Blazor. Recently I have been stuck on showing up a Confirmation Message when user have made change into that and leaves that page.( i.e "Changes have not Saved yet, Are you sure want to leave this page ?") I am sharing my code please refer for understanding. So can anyone guide me through?
mealview.razor.cs File
using Blazored.Modal.Services;
using MealDemoUx.Client.JsInterop;
using MealDemoUx.Client.Services;
using MealDemoUx.Shared.Constants;
using MealDemoUx.Shared.Implementation;
using MealDemoUx.Shared.Services;
using MealDemoUx.Shared.ViewModels;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using Newtonsoft.Json;
namespace MealDemoUx.Client.Pages.MealSelection
{
public partial class AccountMealView
{
[Inject]
private IModalService modal { get; set; }
[Inject]
private IJavascriptInvoker IJavascriptInvoker { get; set; }
[Inject]
private IApiAccountMealSession _accountMealService { get; set; }
[Inject]
private IApiOrganisationMealSession _organisationMealService { get; set; }
[Inject]
private AuthenticationStateProvider AuthenticationStateProvider { get; set; }
[Inject]
private TranslationService _translationService { get; set; }
[Inject]
private IConfiguration _configuration { get; set; }
[Inject]
private LocalAppData localData { get; set; }
[Parameter]
public int classId { get; set; } = 0;
[Parameter]
public long accountId { get; set; } = 0;
public Guid tenantClientId = Guid.Empty;
public Guid controllinggrouptenantclientId = Guid.Empty;
public Guid tenantId = Guid.Empty;
public string OrganisationName = string.Empty;
string langCode = string.Empty;
string EndPoint = string.Empty;
string Key = string.Empty;
string Location = string.Empty;
string AccountName = string.Empty;
public bool IsShowAllowanceAndMealGroup { get; set; } = false;
public bool IsHoliday { get; set; } = false;
public bool IsWeekEnd { get; set; } = false;
public bool IsHideMealGroup { get; set; } = false;
public bool IsHideAllowance { get; set; } = false;
private string baseUrl = string.Empty;
[Inject]
private NavigationManager navManager { get; set; }
public AccountMealViewModel accountMealVM = new AccountMealViewModel();
public AccountMealModel accountMeal = new AccountMealModel();
protected override async Task OnInitializedAsync()
{
baseUrl = navManager.BaseUri;
EndPoint = _configuration.GetSection("TextTranslations").GetValue<string>("EndPoint");
Key = _configuration.GetSection("TextTranslations").GetValue<string>("Key");
Location = _configuration.GetSection("TextTranslations").GetValue<string>("Location");
AccountName = _configuration.GetSection("DemoTransactionQueue").GetValue<string>("AccountName");
langCode = await IJavascriptInvoker.getBlazorCulture();
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
var tenantCltId = user.Claims.Where(c => c.Type == "tenantclientid")
.Select(c => c.Value).SingleOrDefault();
var tenantIdstr = user.Claims.Where(c => c.Type == "tid")
.Select(c => c.Value).SingleOrDefault();
var controllinggrouptenantclientid = user.Claims.Where(c => c.Type == "controllinggrouptenantclientid")
.Select(c => c.Value).SingleOrDefault();
OrganisationName = user.Claims.Where(c => c.Type == "organisationname")
.Select(c => c.Value).SingleOrDefault() ?? string.Empty;
tenantClientId = new Guid(tenantCltId ?? "");
tenantId = new Guid(tenantIdstr ?? "");
controllinggrouptenantclientId = new Guid(controllinggrouptenantclientid ?? "");
IsShowAllowanceAndMealGroup = user.IsInRole(DemoCloudMealDemoConstants.AuthPolicySchoolCateringAdmin) || user.IsInRole(DemoCloudMealDemoConstants.AuthPolicySchoolCaterer);
await LoadOrgDataAsyn();
await LoadAccountMealViewAsync();
}
public async Task SaveAccountMealAsync()
{
if (accountMeal.MealItems == null || accountMeal.MealItems.Count == 0)
{
await IJavascriptInvoker.Alert(SharedLocalizer[DemoCloudMealDemoConstants.cacheKey_SelectOneProduct].Value);
}
else
{
var checkValidation = await IsValidAccountMeal(accountMeal, tenantClientId, langCode);
if (checkValidation.Item1)
{
var apiResponse = await _accountMealService.Create(baseUrl, tenantId, langCode, accountMeal);
if (apiResponse != null)
{
if (apiResponse.isSuccess)
{
var accountData = localData.OrganisationMealSession.Accounts.Where(x => x.AccountId == accountId).FirstOrDefault();
if (accountData != null && !accountData.IsSelected)
{
localData.OrganisationMealSession.Accounts.Remove(accountData);
accountData.IsSelected = true;
localData.OrganisationMealSession.Accounts.Add(accountData);
}
navManager.NavigateTo("/MealSessionClassAccount/View/" + classId);
}
else
{
string msg = apiResponse?.Content.ErrorMsg ?? string.Empty;
if (!string.IsNullOrEmpty(msg) && !string.IsNullOrEmpty(langCode) && langCode != DemoCloudMealDemoConstants.DefaultLangCode)
{
msg = await _translationService.GetTranslatation(EndPoint, Key, Location, msg, langCode);
}
await IJavascriptInvoker.Alert(apiResponse?.Content.ErrorMsg ?? SharedLocalizer[DemoCloudMealDemoConstants.cacheKey_InternalServerError].Value);
}
}
else
{
await IJavascriptInvoker.Alert(SharedLocalizer[DemoCloudMealDemoConstants.cacheKey_InternalServerError].Value);
}
}
else
{
string msg = checkValidation.Item2;
if (!string.IsNullOrEmpty(msg) && !string.IsNullOrEmpty(langCode) && langCode != DemoCloudMealDemoConstants.DefaultLangCode)
{
msg = await _translationService.GetTranslatation(EndPoint, Key, Location, msg, langCode);
}
await IJavascriptInvoker.Alert(msg ?? SharedLocalizer[DemoCloudMealDemoConstants.cacheKey_InternalServerError].Value);
}
}
}
public void Cancel() => navManager.NavigateTo("/MealSessionClassAccount/View/" + classId);
private async Task SelectProduct(ChangeEventArgs args, ProductViewModel product, MealSessionProductGroupViewModel productgroup, string groupId, string elId)
{
var dataAllergyCheck = accountMeal.Allergens.Where(a => a.AccountId == accountId && a.ProductId == product.Id).ToList();
if (dataAllergyCheck != null && dataAllergyCheck.Count() > 0)
{
product.isSelected = false;
await IJavascriptInvoker.ChangeCheckBoxValue(elId);
var allergenData = string.Join(",", dataAllergyCheck.Select(x => string.Join(",", x.AllergenMessage)));
string msg = $"The Account has an allergy, {allergenData}";
if (!string.IsNullOrEmpty(langCode) && langCode != DemoCloudMealDemoConstants.DefaultLangCode)
{
msg = await _translationService.GetTranslatation(EndPoint, Key, Location, msg, langCode);
}
await IJavascriptInvoker.Alert(msg);
}
else
{
var selectedItems = accountMeal.MealItems.Where(x => x.Selected == true && x.ProductGroupId == product.ProductGroupId).Count();
if (Convert.ToBoolean(args.Value) && productgroup.MaxQuantity != 0 && selectedItems >= productgroup.MaxQuantity)
{
product.isSelected = false;
await IJavascriptInvoker.ChangeCheckBoxValue(elId);
string msg = "You may only select " + productgroup.MaxQuantity + " products from " + productgroup.Name;
if (!string.IsNullOrEmpty(langCode) && langCode != DemoCloudMealDemoConstants.DefaultLangCode)
{
msg = await _translationService.GetTranslatation(EndPoint, Key, Location, msg, langCode);
}
await IJavascriptInvoker.Alert(msg);
return;
}
else
{
var isSelected = false;
if (Convert.ToBoolean(args.Value))
{
isSelected = true;
}
var data = accountMeal;
if (accountMeal != null)
{
var mealItem = accountMeal.MealItems.Where(x => x.ProductId == product.Id).OrderByDescending(x => x.MealItemId).FirstOrDefault();
if (mealItem != null && mealItem.MealItemId == 0 && !isSelected)
{
accountMeal.MealItems.Remove(mealItem);
var accountMealItem = new AccountMealItemViewModel
{
Selected = isSelected,
};
}
else if (mealItem != null && mealItem.MealItemId != 0)
{
mealItem.Selected = isSelected;
mealItem.Quantity = isSelected ? 1 : -1;
mealItem.Free = accountMeal.Balance.AllowanceEligibility;
mealItem.Processed = false;
}
else
{
long mealCostId = 0;
var requiredGroupbool = (productgroup.Required || productgroup.Priced ? true : false);
var paidGroupbool = (productgroup.Priced ? true : false);
if (requiredGroupbool && paidGroupbool && data.MealCost != null)
{
mealCostId = data.MealCost.Id;
}
var accountMealItem = new AccountMealItemViewModel
{
MealItemId = 0,
Order = 0,
ProductId = product.Id,
MealCostId = mealCostId,
Selected = isSelected,
Quantity = isSelected ? 1 : -1,
AllergenWarning = false,
Free = accountMeal.Balance.AllowanceEligibility,
PreOrder = false,
Processed = false,
ProductGroupId = product.ProductGroupId
};
accountMeal.MealItems.Add(accountMealItem);
}
}
}
}
}
private async Task SelectPackedLunch(ChangeEventArgs args, long id, List<FundingSourceViewModel> alternativeManagmentModel)
{
var isSelected = false;
if (Convert.ToBoolean(args.Value))
{
isSelected = true;
var ids = string.Join(",", alternativeManagmentModel.Where(x => x.Id != id).Select(x => x.Id).ToList());
await IJavascriptInvoker.UncheckCheckBoxProduct(false, ids);
}
else
{
await IJavascriptInvoker.UncheckCheckBoxProduct(true, string.Empty);
}
var data = accountMeal;
if (accountMeal != null && accountMeal.MealItems != null)
{
if (accountMeal.MealItems.Count > 0)
{
if (isSelected)
{
accountMeal.MealItems = accountMeal.MealItems.Where(x => x.Processed && x.Selected).ToList();
accountMeal.MealItems.ForEach(x =>
{
x.Quantity = -1;
x.Selected = false;
x.Processed = false;
});
}
}
var objaccMeal = accountMeal.MealItems.Where(x => x.PaymentTypeId == id && x.Processed && x.ProductId == 0).FirstOrDefault();
if (objaccMeal != null)
{
objaccMeal.Quantity = isSelected ? 1 : -1;
objaccMeal.Selected = isSelected;
objaccMeal.PaymentTypeId = id;
objaccMeal.Processed = false;
}
else
{
if (isSelected)
{
var accountMealItem = new AccountMealItemViewModel
{
MealItemId = 0,
Order = 0,
ProductId = 0,
MealCostId = 0,
Selected = isSelected,
Quantity = isSelected ? 1 : -1,
AllergenWarning = false,
Free = true,
PreOrder = false,
Processed = false,
ProductGroupId = 0,
PaymentTypeId = id
};
accountMeal.MealItems.Add(accountMealItem);
}
else
accountMeal.MealItems = accountMeal.MealItems.Where(x => x.PaymentTypeId != id).ToList();
}
}
}
private async Task<Tuple<bool, string>> IsValidAccountMeal(AccountMealModel accountMealModel, Guid tenantClientId, string langCode)
{
OrganisationMealSessionViewModel? orgCacheData = null;
var localData = await IJavascriptInvoker.getCacheData(langCode);
if (!string.IsNullOrEmpty(localData))
{
orgCacheData = JsonConvert.DeserializeObject<OrganisationMealSessionViewModel>(localData);
}
var IsValid = true;
var ValidationMsg = "";
if (orgCacheData != null && accountMealModel != null)
{
if (accountMealModel.MealItems != null && accountMealModel.MealItems.Count > 0)
{
var alternativeArrange = accountMealModel.MealItems.Where(x => x.PaymentTypeId > 0 && x.Selected).FirstOrDefault();
if (alternativeArrange == null)
{
var existingItems =
(from mealItems in accountMealModel.MealItems
where mealItems.Processed == true
group mealItems by mealItems.ProductId into playerGroup
select new
{
Id = playerGroup.Key,
Quantity = playerGroup.Sum(x => x.Quantity),
}).Where(x => x.Quantity > 0).Select(x => x.Id).ToList();
var existingWithNewItems =
(from mealItems in accountMealModel.MealItems
group mealItems by mealItems.ProductId into playerGroup
select new
{
Id = playerGroup.Key,
Quantity = playerGroup.Sum(x => x.Quantity),
}).Where(x => x.Quantity > 0).Select(x => x.Id).ToList();
var newSelectedProductIds = accountMealModel.MealItems.Where(x => x.Selected == true && x.Quantity > 0 && x.Processed == false).Select(x => x.ProductId).ToList();
existingWithNewItems.AddRange(newSelectedProductIds);
var checkAllergen = accountMealModel.Allergens.Where(a => a.AccountId == accountMealModel.AccountId && newSelectedProductIds.Contains(a.ProductId)).ToList();
if (accountMealModel.Allergens != null && checkAllergen != null && checkAllergen.Count > 0)
{
IsValid = false;
ValidationMsg = DemoCloudMealDemoConstants.cacheKey_HasAllergen;
}
var productGroups = orgCacheData.ProductGroups.Where(x => x.Products != null && x.Products.Count > 0);
foreach (var pGroup in productGroups)
{
var count = pGroup.Products.Select(x => x.Id).Intersect(existingItems).Count() + pGroup.Products.Select(x => x.Id).Intersect(newSelectedProductIds).Count();
if (count > pGroup.MaxQuantity)
{
IsValid = false;
ValidationMsg = DemoCloudMealDemoConstants.cacheKey_OnlySelect + pGroup.MaxQuantity + DemoCloudMealDemoConstants.cacheKey_ProductFrom + pGroup.Name;
break;
}
if ((pGroup.Priced || pGroup.Required) && !pGroup.Products.Select(x => x.Id).Intersect(existingWithNewItems).Any())
{
IsValid = false;
ValidationMsg = DemoCloudMealDemoConstants.cacheKey_AtLeastOneProduct;
break;
}
}
}
}
}
return new Tuple<bool, string>(IsValid, ValidationMsg);
}
bool UISwitcher;
string Display => UISwitcher == true ? "block;" : "none;";
}
}
JavaScriptInvoker.cs
using DemoRecordererUx.Shared.Constants;
using DemoRecordererUx.Shared.ViewModels;
using Microsoft.JSInterop;
namespace DemoRecordererUx.Client.JsInterop
{
public interface IJavascriptInvoker
{
Task Alert(string msg);
Task SetColor();
Task ChangeCheckBoxValue(string Id);
Task HistoryBack();
Task ShowConfirmBox(string msg);
Task UncheckCheckBoxProduct(bool isChecked, string ids);
Task<string> getBlazorCulture();
Task checkCookie();
Task setCookie();
Task setCacheData(string model, string langCode);
Task<string> getCacheData(string langCode);
Task RemoveLocalCache(string langCode);
Task SetPageExitCheck(bool action);
}
public class JavascriptInvoker : IJavascriptInvoker
{
private readonly IJSRuntime iJSRuntime;
private readonly ILogger<JavascriptInvoker> logger;
private readonly IConfiguration _configuration;
public JavascriptInvoker(IJSRuntime iJSRuntime,
ILogger<JavascriptInvoker> logger, IConfiguration configuration)
{
this.iJSRuntime = iJSRuntime;
this.logger = logger;
this._configuration = configuration;
}
public async Task Alert(string msg)
{
await iJSRuntime.InvokeVoidAsync("Alert", msg);
}
public async Task SetColor()
{
await iJSRuntime.InvokeVoidAsync("SetColor");
}
public async Task ChangeCheckBoxValue(string Id)
{
await iJSRuntime.InvokeVoidAsync("ChangeCheckBoxValue", Id);
}
public async Task HistoryBack()
{
await iJSRuntime.InvokeVoidAsync("HistoryBack");
}
public async Task ShowConfirmBox(string msg)
{
await iJSRuntime.InvokeVoidAsync("ShowConfirmBox", msg);
}
public async Task UncheckCheckBoxProduct(bool isChecked, string ids)
{
await iJSRuntime.InvokeVoidAsync("UncheckCheckbox", isChecked, ids);
}
public async Task<string> getBlazorCulture()
{
string langCode = await iJSRuntime.InvokeAsync<string>("getBlazorCulture") ?? DemoCloudDemoRecordererConstants.DefaultLangCode;
return langCode;
}
public async Task checkCookie()
{
await iJSRuntime.InvokeVoidAsync("checkCookie");
}
public async Task setCookie()
{
await iJSRuntime.InvokeVoidAsync("setCookie");
}
public async Task setCacheData(string model, string langCode)
{
await iJSRuntime.InvokeVoidAsync("setCacheData", $"{DemoCloudDemoRecordererConstants.LocalCacheKey}-{langCode}", model);
}
public async Task<string> getCacheData(string langCode)
{
string LocalCacheExpiryInMin = _configuration.GetValue<string>("LocalCacheExpiryInMin");
return await iJSRuntime.InvokeAsync<string>("getCacheData", $"{DemoCloudDemoRecordererConstants.LocalCacheKey}-{langCode}", LocalCacheExpiryInMin);
}
public async Task RemoveLocalCache(string langCode)
{
await iJSRuntime.InvokeVoidAsync("RemoveLocalCache", $"{DemoCloudDemoRecordererConstants.LocalCacheKey}-{langCode}");
}
public async Task SetPageExitCheck(bool action) => iJSRuntime.InvokeAsync<bool>("blazr_setEditorExitCheck", action);
}
}
DemoMeal.js file
window.blazorCulture = {
get: () => window.localStorage['BlazorCulture'],
set: (value) => window.localStorage['BlazorCulture'] = value
};
window.SetColor = function () {
var foreColour = $("#foreColour").val();
var backcolour = $("#backColour").val();
$(".classaccountsetcolour").css({
"color": foreColour,
"background-color": backcolour
});
}
window.Alert = function (message) {
alert(message);
}
window.HistoryBack = function () {
window.history.back();
}
window.ChangeCheckBoxValue = function (id) {
$("#" + id).prop('checked', false);
}
window.ShowConfirmBox = function (msg) {
var con = confirm(msg);
if (!con) {
window.history.back();
}
}
window.UncheckCheckbox = function (isChecked, ids) {
if (isChecked) {
$("#tblProductListByGroup").removeClass("d-none");
} else {
// uncheck Meal Item checkbox
$('input[name="product_checkbox"]').each(function () {
this.checked = false;
});
$("#tblProductListByGroup").addClass("d-none");
if (ids != null && ids != '') {
// uncheck Other AlterNative checkbox
let arrayIds = ids.split(',');
$(arrayIds).each(function (index, id) {
$("#alter_" + id).prop("checked", false);
});
}
}
}
window.getBlazorCulture = function () {
return window.localStorage['BlazorCulture'];
};
window.setBlazorCulture = function (value) {
window.localStorage['BlazorCulture'] = value;
};
window.checkCookie = function () {
// check cookie
let visited = '';
let name = "visited=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
visited = c.substring(name.length, c.length);
}
}
if (visited == null || visited == '') {
$('.cookie-consent').show();
}
else {
$('.cookie-consent').hide();
}
};
window.setCookie = function () {
// set cookie
const d = new Date();
d.setTime(d.getTime() + (365 * 24 * 60 * 60 * 1000));
let expires = "expires=" + d.toUTCString();
document.cookie = "visited=yes;" + expires + ";path=/";
$('.cookie-consent').hide();
};
window.toggleMenu = function () {
let menuList = document.getElementById("menuList");
menuList.style.maxHeight = "0px";
if (menuList.style.maxHeight == "0px") {
menuList.style.maxHeight = "130px";
}
else {
menuList.style.maxHeight = "0px";
}
};
window.setCacheData = function (key, value, expiryMins) {
const now = new Date();
const item = {
value: value,
expiry: now.getTime(),
}
window.sessionStorage[key] = JSON.stringify(item);
}
window.getCacheData = function (key, expiryMins) {
const itemStr = sessionStorage.getItem(key);
let expirationDuration = 1000 * 60 * expiryMins;
// if the item doesn't exist, return null
if (!itemStr) {
return null
}
const item = JSON.parse(itemStr);
const now = new Date();
const cacheDate = new Date(item.expiry);
// compare the expiry time of the item with the current time
if (now.getTime() > (item.expiry + expirationDuration) || (cacheDate.getDate() !== now.getDate() || cacheDate.getMonth() !== now.getMonth() || cacheDate.getFullYear() !== now.getFullYear())) {
// If the item is expired, delete the item from storage
// and return null
sessionStorage.removeItem(key)
return null
}
return item.value;
}
window.RemoveLocalCache = function (key) {
const itemStr = sessionStorage.getItem(key);
if (itemStr) {
window.sessionStorage.removeItem(key);
}
}
window.blazr_setEditorExitCheck = function (show) {
if (show) {
window.addEventListener("beforeunload", blazr_showExitDialog);
}
else {
window.removeEventListener("beforeunload", blazr_showExitDialog);
}
}
window.blazr_showExitDialog = function (event) {
event.preventDefault();
event.returnValue = "There are unsaved changes on this page. Do you want to leave?";
}