How to use enum value in checkbox and store the accourding in integer number?

Viewed 83

I have a string property that corresponds have some checkbox values. I want to use an enum. Enum values want to store on that string property.

My property is in the Model class. It has many properties. I just put only two properties and enum:

public class Client_CIPEnergyCrisis
{

    [Display(Name = "What type of assistance are you seeking?")]
    public string AssistanceType { get; set; }
    
    [NotMapped]
    public List<int> AssistanceTypeList { get; set; }
}

public enum AssistanceTypes
{
    [Display(Name = "Assistance with Disconnection")]
    AssistanceWithDisconnection = 1,

    [Display(Name = "Utility Pole/ Gas line Hookup or Deposit")]
    UtilityGaslineHookup = 2,

    [Display(Name = "Emergency Heating Fuel")]
    EmergencyHeatingFuel = 3,

    [Display(Name = "System Repair or Replacement")]
    SystemRepair = 4,

    [Display(Name = "Anything else ?")]
    Anything = 5,
}

This is my view page. That is a partial view. It's used for Insert and Update data.

@model Client_CIPEnergyCrisis

<div><label asp-for="AssistanceType" class="form-label"></label></div>

@foreach (var assistanceType in Enum.GetValues<AssistanceTypes>())
{
    <div class="col-md-4 pt-2">
        <input class="form-check-input" type="checkbox" value="@((int)assistanceType)" name="AssistanceTypeList">
        <label class="form-check-label" for="flexCheckChecked"> @Html.DisplayFor(model => assistanceType) </label>
    </div>
}

This is my Add Razor Page add.cshtml page. Here have multiple partial views. We can ignore it. We are passed the needed model.

  @page
@model AddCIPEnergyCrisisModel


@{
    ViewData["Title"] = "CIP Energy Crisis";
}

<partial name="_DataFormTitlePartial" model='new string("New CIP Energy Crisis")' />

<div class="card dataForm mb-3">
    <form method="post">
        <partial name="_FamilyIncomeInfoPartial" model="@Model.FamilyIncomeList" />
        <partial name="_CIPEnergyCrisisPartial" model="@Model.CIPEnergyCrisis" />
        <partial name="_SaveCancelPartial" model="@Model.CCInfo" />
    </form>
</div>**strong text**

This is add.cshtml.cs Page.

 [BindProperty]
     public List<int> AssistanceTypeList { get; set; }
    
     [BindProperty]
     public Client_CIPEnergyCrisis CIPEnergyCrisis { get; set; }
     public IActionResult OnPost()
            { var selectedAssistantType = string.Join(",", AssistanceTypeList);
                    CIPEnergyCrisis.AssistanceType = selectedAssistantType;
    }

Add feature work well. But when I go to edit. then I face the problem.

This is my Edit Razor Page edit.cshtml.cs page. Here have multiple partial views. We can ignore it. We are passed the needed model.

 public void OnGet(int Id)
        {
            try
            {
                CIPEnergyCrisis = new Client_CIPEnergyCrisis();
                var data = serviceManager.GetClient_CIPEnergyCrisis(Id);

                var selectedAssistantType = data.AssistanceType;

                CIPEnergyCrisis.AssistanceTypeList = selectedAssistantType
                    .Split(",")
                    .Select(int.Parse)
                    .ToList();
            }
        }

Maybe I need a if condition in partial page. But I can't do that. may you help me please....

1 Answers

First approach:

You can bind the selected checkbox values to a list of integers then convert the list to comma separated string inside OnPost method. Notice that the name attribute of the checkboxes name="AssistanceTypeList" has the same name as the bound property public List<int> AssistanceTypeList { get; set; }. This is important.

Page:

<div class="col-md-4 pt-2">
    <input class="form-check-input" type="checkbox" value="@((int)AssistanceTypes.AssistanceWithDisconnection)" name="AssistanceTypeList"
           checked="@(Model.AssistanceTypeList.Contains((int)AssistanceTypes.AssistanceWithDisconnection))">

    <label class="form-check-label" for="flexCheckChecked"> Assistance with Disconnection </label>
</div>
<div class="col-md-4 pt-2">
    <input class="form-check-input" type="checkbox" value="@((int)AssistanceTypes.UtilityGaslineHookup)" name="AssistanceTypeList"
           checked="@(Model.AssistanceTypeList.Contains((int)AssistanceTypes.UtilityGaslineHookup))">

    <label class="form-check-label" for="flexCheckChecked"> Utility Pole/ Gas line Hookup or Deposit </label>
</div>
<div class="col-md-4 pt-2">
    <input class="form-check-input" type="checkbox" value="@((int)AssistanceTypes.EmergencyHeatingFuel)" name="AssistanceTypeList"
           checked="@(Model.AssistanceTypeList.Contains((int)AssistanceTypes.EmergencyHeatingFuel))">

    <label class="form-check-label" for="flexCheckChecked"> Emergency Heating Fuel </label>
</div>
<div class="col-md-4 pt-2">
    <input class="form-check-input" type="checkbox" value="@((int)AssistanceTypes.SystemRepair)" name="AssistanceTypeList"
           checked="@(Model.AssistanceTypeList.Contains((int)AssistanceTypes.SystemRepair))">

    <label class="form-check-label" for="flexCheckChecked"> System Repair or Replacement </label>
</div>
<div class="col-md-4 pt-2">
    <input class="form-check-input" type="checkbox" value="@((int)AssistanceTypes.Anything)" name="AssistanceTypeList"
           checked="@(Model.AssistanceTypeList.Contains((int)AssistanceTypes.Anything))">

    <label class="form-check-label" for="flexCheckChecked"> Anything else ?  </label>
</div>

PageModel:

[BindProperty]
public List<int> AssistanceTypeList { get; set; }

public void OnGet()
{
    var selectedAssistantType = data.AssistanceType;
        
    AssistanceTypeList = selectedAssistantType
        .Split(",")
        .Select(int.Parse)
        .ToList();
}

public void OnPost()
{
    // AssistanceTypeList contains the enum values that where checked by the user. We just need to convert the list to comma separated string.
    
    var selectedAssistantType = string.Join(",", AssistanceTypeList);
}

Second approach (my recommendation):

First of all use the Display attribute to set the display name for each enum value. The display name will be shown inside the label of each checkbox.

public enum AssistanceTypes
{
    [Display(Name = "Assistance with Disconnection")]
    AssistanceWithDisconnection = 0,

    [Display(Name = "Utility Pole/ Gas line Hookup or Deposit")]
    UtilityGaslineHookup = 1,

    [Display(Name = "Emergency Heating Fuel")]
    EmergencyHeatingFuel = 2,

    [Display(Name = "System Repair or Replacement")]
    SystemRepair = 3,

    [Display(Name = "Anything else ?")]
    Anything = 4,
}

Inside your Page, instead of creating each checkbox "manually", iterate the AssistanceTypes values and create a checkbox for each value. Use @Html.DisplayFor html helper to get the friendly display names for the labels.

@foreach (var assistanceType in Enum.GetValues<AssistanceTypes>())
{
    <div class="col-md-4 pt-2">
        <input class="form-check-input" type="checkbox" value="@((int)assistanceType)" name="AssistanceTypeList"
               checked="@(Model.AssistanceTypeList.Contains((int)assistanceType))">

        <label class="form-check-label" for="flexCheckChecked"> @Html.DisplayFor(model => assistanceType) </label>
    </div>
}

The PageModel stays the same.

This way if in the future you need to add new values to the AssistanceTypes enum. You don't need to change anything in your Page and PageModel.

https://www.learnrazorpages.com/razor-pages/forms/checkboxes#binding-to-collections

How to use inside a partial example:

_AssistanceTypePartial.cshtml:

@model List<int>

@foreach (var assistanceType in Enum.GetValues<AssistanceTypes>())
{
    <div class="col-md-4 pt-2">
        <input class="form-check-input" type="checkbox" value="@((int)assistanceType)" name="AssistanceTypeList"
               checked="@(Model.Contains((int)assistanceType))">

        <label class="form-check-label" for="flexCheckChecked"> @Html.DisplayFor(model => assistanceType) </label>
    </div>
}

Inside your view page:

<div class="col-md-12 row ">
    <partial name="_AssistanceTypePartial"
             model="@Model.AssistanceTypeList">

    <div class="col-md-4 pt-2">
        <input type="text" class="form-control" placeholder="Explain" />
    </div>
</div>
Related