'How do I get results from dynamically created radio buttons?
EDIT I tried the suggested changes in the first answer but I was getting radio buttons that could be chosen more than once and the label number was controlling the top radio button. Since then I've tinkered..I'll do my best to explain.
I'm new to Razor Pages and .Net and I've set myself a project where I create questions and their Category and Display Order into a table in SQL i.e. Order: 1 Category: 'Azure' Question: 'Rate your knowledge on Azure Databricks'
In a separate Page I am then pulling the list of questions in on a @foreach. This results in a Web page with Category, Questions and Radio Buttons in order. I have 5 Radio Buttons being inserted below each questions and Radios play nicely with each other, but on clicking the Submit button it just brings (inserts into my table) 1 blank record.
Here's a shortened version of the code:
I want to (get question details from table [Category] > Create Question page > Collate RadioButton Entries into [Category2] table)
Edited version
using GaryGaryGary.BaconModels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using BaconDataAccess;
using BaconModels;
namespace GaryGaryGary.Pages.Questions
{
[BindProperties]
public class QuestionsModel : PageModel
{
private readonly ApplicationDbContext _db;
public QuestionsModel(ApplicationDbContext db)
{
_db = db;
}
[BindProperty]
//These lists are pulled out of the Categpory table and displayed as Questions in the Questions Page
public IEnumerable<Category> Web { get; set; }
public IEnumerable<Category> Agile { get; set; }
public IEnumerable<Category> Code { get; set; }
public IEnumerable<Category> Testing { get; set; }
public IEnumerable<Category> Microsoft { get; set; }
public IEnumerable<Category> Azure { get; set; }
//Pulling the Lists and using lambda to organise them into an order, as per the table they are coming from
public async Task OnGet()
{
Web = await _db.Category.Where(x => x.Skill == "Web").OrderBy(s => s.DisplayOrder).ToListAsync();
Agile = await _db.Category.Where(x => x.Skill == "Agile").OrderBy(s => s.DisplayOrder).ToListAsync();
Code = await _db.Category.Where(x => x.Skill == "Code").OrderBy(s => s.DisplayOrder).ToListAsync();
Testing = await _db.Category.Where(x => x.Skill == "Testing").OrderBy(s => s.DisplayOrder).ToListAsync();
Microsoft = await _db.Category.Where(x => x.Skill == "Microsoft").OrderBy(s => s.DisplayOrder).ToListAsync();
Azure = await _db.Category.Where(x => x.Skill == "Azure").OrderBy(s => s.DisplayOrder).ToListAsync();
}
//This is where I want to send the Data to. Currently the receiving Category2 table has the same column setup as the Category table.
//This does grab the username and role as long as no Radios are chosen??? Feeling very out of my depth
[BindProperty]
public Category2 Category2 { get; set; }
///in this bit I now want to catch all of the entries made into the Radio buttons as well the User Name and Department > See HTML
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
await _db.Category2.AddAsync(Category2);
await _db.SaveChangesAsync();
return RedirectToPage("../Index");
}
}
}
@page
@model GaryGaryGary.Pages.Questions.QuestionsModel
@{
}
<div>
<h1 class="text-center text-green">Project Questionnaire</h1>
<br />
</div>
<form asp-action="Submit" asp-controller="Questions">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group form-group-inline">
<label asp-for="Category2.User" class="control-label"></label>
<input asp-for="Category2.User" class="form-control" />
<span asp-validation-for="Category2.User" class="text-danger"></span>
</div>
<div class="form-group form-group-inline">
<label asp-for="Category2.Role" class="control-label"></label>
<input asp-for="Category2.Role" class="form-control" />
<span asp-validation-for="Category2.Role" class="text-danger"></span>
</div>
@*// I would like for the above (Username and Role) to get carried into the table along with the corresponding answers . Should it be in the loop to and hidden maybe? *@
<h1 class="text-warning">Azure and Cloud Applications 😎</h1>
@{
int i=0; //Index gets added as per 1st Answer
int j = 0; //Index gets added as per 1st Answer
}
@*The foreach grabs the list from the code behind and uses it to display the order number and question. 5 Radio buttons then follow. In this example I tried naming the group Category2 but I've tried all sorts. So confused?*@
@foreach (var obj in Model.Azure)
{
<fieldset class="ml-3 form-group">
<legend>@obj.DisplayOrder : @obj.Question </legend>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option1" type="radio" name="Category2[@i]" class="form-check-input" value="r1">
<label id="Azure1">1</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option2" type="radio" name="Category2[@i]" class="form-check-input" value="r2">
<label id="Azure2">2</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option3" type="radio" name="Category2[@i]" class="form-check-input" value="r3">
<label id="Azure3">3</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option4" type="radio" name="Category2[@i]" class="form-check-input" value="r4">
<label id="Azure4">4</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option5" type="radio" name="Category2[@i]" class="form-check-input" value="r5">
<label id="Azure5">5</label>
</div>
</fieldset>
i++; //Index counts each loop
}
<br />
@*Next foreach group does the same for the next topic. Here I added .a to the name becuase otherwise all Radio buttons are grouped and start arguing. If I gave them a unique name, how do I then grab that info?*@
<h1 class="text-warning">⛅ Web and Cloud Knowledge 🕸</h1>
@foreach (var obj in Model.Web)
{
<fieldset class="ml-3 form-group">
<legend>@obj.DisplayOrder : @obj.Question </legend>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option1" type="radio" name="Category2[@j].a" class="form-check-input" value="r1">
<label id="WebResult1">1</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option2" type="radio" name="Category2[@j].a" class="form-check-input" value="r2">
<label id="WebResult2">2</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option3" type="radio" name="Category2[@j].a" class="form-check-input" value="r3">
<label id="WebResult3">3</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option4" type="radio" name="Category2[@j].a" class="form-check-input" value="r4">
<label id="WebResult4">4</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option5" type="radio" name="Category2[@j].a" class="form-check-input" value="r5">
<label id="WebResult5">5</label>
</div>
</fieldset>
j++; //Index counts each loop
}
<br />
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
@*They'll be a few more foreach loop lists to come that will pick up the other lists from the page control*@
Happy to provide code from elsewhere (table setup etc.) if required, and comfortable with creating a new table to receive the results. Currently the receiving table is setup with the same model as the table holding the questions but I can't get anything worth while back from the questions page? This is my first time at doing this so apologies if there is any bad code or practice.
Solution 1:[1]
Model binding binds the property by name attribute. Your name attribute does not match the backend propety.
@{
int i=0; //add index...
int j = 0;
}
@foreach (var obj in Model.Azure)
{
<fieldset class="ml-3 form-group">
<legend>@obj.DisplayOrder : @obj.Question </legend>
<div class="form-check form-check-inline"> //change all the name attributes...
<input asp-for="Category2.Option1" type="radio" name="Azure[@i].Option1" class="form-check-input" value="r1">
<label id="Azure" asp-for="Category2.Option1">1</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option2" type="radio" name="Azure[@i].Option2" class="form-check-input" value="r2">
<label id="Azure" asp-for="Category2.Option2">2</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option3" type="radio" name="Azure[@i].Option3" class="form-check-input" value="r3">
<label id="Azure" asp-for="Category2.Option3">3</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option4" type="radio" name="Azure[@i].Option4" class="form-check-input" value="r4">
<label id="Azure" asp-for="Category2.Option4">4</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option5" type="radio" name="Azure[@i].Option5" class="form-check-input" value="r5">
<label id="Azure" asp-for="Category2.Option5">5</label>
</div>
</fieldset>
i++; //add this.....
}
<h1 class="text-warning">Web Knowledge ?</h1>
@foreach (var obj in Model.Web)
{
<fieldset class="ml-3 form-group">
<legend>@obj.DisplayOrder : @obj.Question </legend>
<div class="form-check form-check-inline"> //change all the name attributes...
<input asp-for="Category2.Option1" type="radio" name="Web[@j].Option1" class="form-check-input" value="r1">
<label id="WebResult" asp-for="Category2.Option1">1</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option2" type="radio" name="Web[@j].Option2" class="form-check-input" value="r2">
<label id="WebResult" asp-for="Category2.Option2">2</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option3" type="radio" name="Web[@j].Option3" class="form-check-input" value="r3">
<label id="WebResult" asp-for="Category2.Option3">3</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option4" type="radio" name="Web[@j].Option4" class="form-check-input" value="r4">
<label id="WebResult" asp-for="Category2.Option4">4</label>
</div>
<div class="form-check form-check-inline">
<input asp-for="Category2.Option5" type="radio" name="Web[@j].Option5" class="form-check-input" value="r5">
<label id="WebResult" asp-for="Category2.Option5">5</label>
</div>
</fieldset>
j++; //add this...
}
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
Then you can find the Web and Azure properties get the selected option with value:
public IEnumerable<Category> Web { get; set; }
public IEnumerable<Category> Azure { get; set; }
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Rena |

