Home > Software engineering >  How to read multiple choice answers from a dynamic form in razor pages?
How to read multiple choice answers from a dynamic form in razor pages?

Time:09-19

As a follow up on my previous question related to this issue, the solution provided there works well enough for basic answers to basic questions in my questionnaire.

Background

I'm allowing the user to create custom questionnaires by specifying question details including a question type which determines the UI elements that will be rendered dynamically when their customer fills out the questionnaire.

The proposed solution of binding in a list per learnrazorpages.com works well for questions for which only one response may be given, however, it seems less apt for handling a multiple choice type of question where the user may provide any number of responses.

The following code does not inject my selections on the multiple choice question into the form submission.

<form method="post">
    @for (int i = 0; i <= Model.Questions.Count - 1; i  )
    {
        var question = Model.Questions[i];
        var questionId = Model.Questions[i].Id;
        var questionType = Model.Questions[i].Type;

        <input type="hidden" id="[@i].QuestionId" name="[@i].QuestionId" value="@questionId" />

        @if (questionType == Enums.QuestionType.MultipleChoice)
        {
            var options = Model.Options.Where(x => x.Question.Id == questionId);
            var answers = Model.Answers.WHere(x => x.Question.Id == questionId);

            <div >
                <p >@question.Text</p>

                @for (int j = 0; j <= Model.Options.Count() - 1; j  )
                {
                    if (Model.Options[j].Question.Id == questionId)
                    {
                        // Determine based on the answer whether or not to check the checkbox.
                        var option = Model.Options[j];

                        var isChecked = answers.Any(x => x.Value == option.Id.ToString());
                        var _checked = isChecked ? "checked" : "";

                        <div>
                            <input type="hidden" id="[@j].OptionId" name="[@j].OptionId" value="@option.Id" />
                            <input  type="checkbox" id="[@j].Value" name="[@j].Value" value="@option.Id" @_checked />
                            <label  for="[@j].Value">@option.Text</label>
                        </div>
                    }
                }
            </div>
        }
</form>

I structured it this way thinking it would simply inject the options list into the method parameter value of my OnPost method, since the viewmodel I built for that method accepts the list as a parameter:

public void OnPost(List<AnswerViewmodel> answers)
{
    // I haven't got any logic here yet to save the answers so this is just for a breakpoint.
    var answered = answers.Where(x => x.Value is not null);
}

public class AnswerViewmodel
{
    public int QuestionId { get; set; }
    public string Value { get; set; }
    public string Comment { get; set; }
    public List<OptionViewmodel> Options { get; set; }
}

public class OptionViewmodel
{
    public int OptionId { get; set; }
    public string Value { get; set; }
}

If the option is selected (checked) then Value will be "true", otherwise "false".

However, the Options list is always null in the value.

How can I get my options to post through to the backend with the rest of the form?

CodePudding user response:

You name attribute of your inputs should be [@i].Options[@j].Value to bind correctly with the List<OptionViewmodel> Options:

<input type="hidden" id="[@j].OptionId" name="[@i].Options[@j].OptionId" value="@option.Id" />
<input  type="checkbox" id="[@j].Value" name="[@i].Options[@j].Value" value="@option.Id" @_checked />
  • Related