'Blazor Form with Dynamic Number of Questions
I'm trying to create a testing application that pulls question/data answer from a database. The tests each have a different number of questions (some 10, some 15, some 12) that all need to be displayed with their answer choices (some multiple choice with 4 or 5 answers, some true/false). I want to utilize the Blazor form structure to allow access to input validation, but it seems that the form Model has to have a static number of members (i.e. only 10 test questions). I tried binding the form to a class with a List of length n, where n is the number of test questions (and consequently, the number of answers), but that only recorded the first answer despite setting the @bind-Value to separate indexes of the List.
Is it at all possible to utilize dynamic data structures in Blazor Form Modeling or should I look at doing something different?
Edit: For the sake of clarity, let me dump my code here. I'm using the Radzen form libraries, which can be found here. All relevant data structures and initializers can be found below, as well.
My question lies in where I bind the RadioButtonList to the answer model: @[email protected][curr.Key]. Can I do this? I'm currently getting an 'index out of bounds' error in that statement.
Some code:
<RadzenTemplateForm TItem="Answers" Data=@selectedAnswers Submit=@GradeExam>
@foreach (KeyValuePair<int, List<string>> curr in shuffledAnswers){
<RadzenCard>
<label class="col 2 font-weight-bold"><strong>@curr.Key) @allQuestions[curr.Key.ToString()].question</strong></label>
<RadzenRadioButtonList
@[email protected][curr.Key]
TValue="int" Name=@(curr.Key.ToString())
Orientation="Radzen.Orientation.Vertical"
>
<Items>
@foreach (string s in curr.Value){
<RadzenRadioButtonListItem Text=@s [email protected](s) />
Console.WriteLine("radio button");
}
</Items>
</RadzenRadioButtonList>
<RadzenRequiredValidator Component=@(curr.Key.ToString()) Text="This question is required." Popup="true" />
@if(submitted){
<br/><label class="col 2 font-weight-bold"><em>@allQuestions[curr.Key.ToString()].tooltip</em></label>
}
</RadzenCard>
}
<RadzenCard>
@if(!submitted){
<RadzenButton ButtonType="Radzen.ButtonType.Submit" Text="Submit" style="background-color: royalblue;" />
}
else {
<!-- go back to course list -->
}
</RadzenCard>
</RadzenTemplateForm>
@code{
// test answer binding model
private class Answers{
List<string> Answers;
public TestAnswers(){
Answers = new List<string>();
}
}
private Answers selectedAnswers;
private Dictionary<int, List<string>> shuffledAnswers;
private Dictionary<string, Question> allQuestions;
// ^ Question class contains the question and associated answers
private void ShuffleAnswers{
// iterate through all question data
foreach(KeyValuePair<string, Question> q in allQuestions){
// generate temporary string to hold answers
List<string> temp = new List<string>();
temp.Add(q.Value.correct);
temp.Add(q.Value.wrong1);
// if multiple choice w/ 4 answers, add them too
if(q.Value.wrong2 != "N/A"){
temp.Add(q.Value.wrong2);
temp.Add(q.Value.wrong3);
}
List<string> ans = new List<string>();
shuffledAnswers.Add(int.Parse(q.Key), ans);
// move a random answer from temp to the list of shuffled answers
while(temp.Count > 0){
int index = new Random(DateTime.Now.GetHashCode()).Next(temp.Count);
shuffledAnswers[int.Parse(q.Key)].Add(temp[index]);
temp.RemoveAt(index);
}
// initialize selected answer indexes
selectedAnswers.testAnswers.Add(0);
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
